ZK - concatenate a variable with a constant string in a map key in ZUL EL - el

A have a custom translator object implementing java.util.Map in the page scope un I use it like
<checkbox id="cbCopy" label='${translator.copy}' />
It works fine also for hierarchical keys using the more complex map syntax of EL:
<checkbox id="cbCopy" label='${translator['hierarchical.key.copy']}' />
It also works when I have the key in a variable:
<zscript>
desktopScope.put("someKey",sessionScope.get("customerCompany")+".copy");
</zscript>
<checkbox id="cbCopy" label='${translator[someKey]}' />
My problem is to compose the hierarchical key in the EL expression concetanating a variable and a constant string:
<zscript>
desktopScope.put("customerCompany",sessionScope.get("customerCompany")+".");
</zscript>
<checkbox id="cbCopy" label='${translator[customerCompany+'copy']}' /> <!-- DOES NOT WORK!!! -->
Ist it somehow possible?
The reason is that several (but not all) ZUL GUI component on the page needs this kind of composite i18n keys.

Since ZK 8, you can concatenate a string with +=:
${translator[customerCompany+='copy']}
Ref: https://github.com/zkoss/zkbooks/blob/master/developersreference/developersreference/src/main/webapp/uiComposing/elExpression.zul
In previous version, you can use tag library, cat.

Related

Component mounted twice

I have a simple component which is rendered by a click function, but it gets rendered twice, this is my code.
<SeeCompany
:is="create"
v-bind:companyId="companySelected"
#closeChild="closeModule"
/>
when i clicked in the button i change the create value to 'SeeCompany' so it gets mounted, but it repeats the same component text twice on the screen.
<b-button block
#click="create = 'SeeCompany'"
class="m-sides"
variant="outline-primary">
Ver
</b-button>
here is the image:
EDIT: Here is the code in the mounted
export default class SeeCompany extends Vue {
#Prop({ default: 0 }) private companyId !: number;
constructor() {
super();
}
private mounted() {
console.log(this.companyId); --> This is consoling two ceros (0) and the passed value for instance = 1;
}
}
There are two main uses for is.
Working around limitations in in-DOM templates.
Dynamic components.
For more information see https://v2.vuejs.org/v2/api/#is.
We can ignore the former case as it isn't relevant here.
Typically the second case looks a bit like this:
<component :is="childName" />
Here childName is a property of the component and determines the name of the child component to use. In your example you called it create.
The actual tag name used in the template doesn't really matter. It is common to use the dummy tag <component> for this purpose to avoid misleading future maintainers who may not immediately notice the :is. Whenever you see <component> you know you're in a dynamic component scenario.
When we talk about dynamic components it is important to appreciate exactly what we mean by 'dynamic' in this context. We are specifically talking about which component to use. We are not talking about determining whether or not to create the component in the first place.
In the code in the question the value of create is initially set to an empty string, ''. This is then passed to :is. If you inspect the DOM you'll find that this creates a comment node. While this does make some sense I am unclear if this is officially supported. I've not seen this behaviour documented anywhere and I suspect you may be getting lucky by falling down an internal code path that's intended for other things. It is not something I would be confident relying on in future versions of Vue.
The specific code of interest is:
<SeeCompany
v-bind:is="create"
v-bind:companyId="1"
/>
<SeeOther
v-bind:is="create"
v-bind:companyId="1"
/>
So if you inspect the DOM when create is '' you should find two comment nodes.
When create gets set to SeeCompany this is equivalent to:
<SeeCompany
is="SeeCompany"
v-bind:companyId="1"
/>
<SeeOther
is="SeeCompany"
v-bind:companyId="1"
/>
In turn this is equivalent to:
<SeeCompany
v-bind:companyId="1"
/>
<SeeCompany
v-bind:companyId="1"
/>
The result is the creation of two SeeCompany components. The original SeeOther tag is irrelevant here. This is why, as noted earlier, the convention exists to use a <component> tag to avoid being misleading.
Of course this isn't what you actually wanted the code to do. I'm unclear what the target behaviour is so I'm going to cover a few variations.
If you just want to show the components conditionally you'd use v-if instead:
<SeeCompany
v-if="create"
v-bind:companyId="1"
/>
<SeeOther
v-if="create"
v-bind:companyId="1"
/>
Usually you'd want create to be a proper boolean, false or true. So set the initial value to false with #click="create = true".
Of course this would show both SeeCompany and SeeOther at the same time. That may not be what you want either. Perhaps you only want to show one at once. For that you might do something like this:
<SeeCompany
v-if="create === 'SeeCompany'"
v-bind:companyId="1"
/>
<SeeOther
v-if="create === 'SeeOther'"
v-bind:companyId="1"
/>
Here the initial value of create should be a falsey value of some kind, possibly '', with #click="create = 'SeeCompany'" and #click="create = 'SeeOther'" on appropriate buttons.
If the props for the components are all the same, and especially if there are more than two components involved, you could try to simplify this using is:
<component
:is="create"
v-if="create"
v-bind:companyId="1"
/>
This is shorter but arguably not as clear.

Vue Dynamic Component Ordering?

Thanks in advance for the help.
I'm using the Vue's dynamic component tag in an application.
https://v2.vuejs.org/v2/guide/components.html#Dynamic-Components
The component list is provided via a computed property which I simply iterate over creating <component /> elements.
<component v-for="component in myComponents" :key="component" is="component />
The issue i'm running into is the components are loaded asynchronously and some components can take longer at times than others to load. Due to this sometimes the components load out of the desired order.
I was curious if anyone had a suggestion on how I might be able to force the components to display in a desired order?
You can try to use an ordered computed property, for exemple if you want to order your components by name.
In the template :
<component v-for="component in orderedComponents" :key="component" is="component />
In the script
computed: {
orderedComponents: function () {
return _.orderBy(this.myComponents, 'name')
}
}
This exemple is using Lodash but of course you can order it the way you want.
You can check the documentation : https://v2.vuejs.org/v2/guide/migration.html#Replacing-the-orderBy-Filter
Yes, you can enforce the order by setting :key to a number.
First, modify your for loop to use indexes:
v-for="(index, value) in myComponents"
Then set key to the index
:key="index"
This should keep the order in tact - if it doesn't, you could always create placeholders first then replace them in the runtime.

What is the suitable replacement for this.__LZtextclip.text in Open laszlo 5.0

I want to know what is the suitable replacement for this line.
this.__LZtextclip.text
I am using this to get the string present in the text node. This works fine in Openlaszlo 3.3 but in 4.9 and 5.0 it's giving a problem
I tried updating it to
this.sprite.__LZtextclip.text
And i am getting an error:
79: Error: Access of possibly undefined property __LZtextclip through a reference with static type LzSprite, in line: Debug.write(this.sprite.__LZtextclip.text);
Any idea why this problem is happening?
If you are trying to access the text content of a text field, why don't you just access the attribute text?
<canvas>
<text name="sample" id="gRead" />
<handler name="oninit">
gRead.setAttribute('text',"HI");
Debug.info(gRead.text);
</handler>
</canvas>
In OpenLaszlo 3.3 there is method getText(), which gives you the same value. Accessing mx.textfield in your code does not work for the DHTML runtime.
Edit: Added information regarding the stripping of HTML tags
The Flash Textfield class flash.text.Textfield provides an API to enable HTML tag content in a Textfield instance. There are two different properties, one called text, the other one htmlText. If you want to directly access the Flash Textfield object of an lz.text instance, it's a property of the display object of the lz.text instance:
// Flash Textfield instance
gRead.getDisplayObject().textfield
// Pure text content
gRead.getDisplayObject().textfield.text
// Formatted text
gRead.getDisplayObject().textfield.htmlText
You should be aware of the fact that Flash automatically adds HTML format to any textstring you set as content. When you do
gRead.setAttribute('text',"HI");
the textfield.htmlText value is
<P ALIGN="LEFT"><FONT FACE="Verdana" SIZE="11" COLOR="#000000" LETTERSPACING="0" KERNING="1">HI</FONT></P>
For the DHTML runtime, the text content is added as the innerHTML of a <div> tag, and there is no standardized API to retrieve the pure text content of a DOM structure for a tag with content. You could write your own function to extract the text content, or use JavaScript functions from existing frameworks - like the jQuery text() function - to achieve the same result for the DHTML runtime.
I guess the reason is that Laszlo started using the Dojo based rich text editor for text input with HTML formatting since OpenLaszlo 4.0 or 4.1.
The best approach to have consistent behavior across runtimes when stripping tags is to do the conversion on the server-side. That's especially needed if you wan to have consistent whitespace treatment in multiline text, since there differences in how browsers treat whitespace. The question how to best strip tags from strings in JavaScript has been answered before on Stackoverflow, e.g. JavaScript: How to strip HTML tags from string?
Here is a cross-runtime example which works in DHTML with Firefox, Chrome, and it should work with IE9+:
<canvas>
<text name="sample" id="gRead" />
<handler name="oninit"><![CDATA[
gRead.setAttribute("text", 'Hello <b>World</b> OL');
Debug.info("gRead.text=" + gRead.text);
if ($dhtml) {
Debug.info(gRead.getDisplayObject().textContent);
} else {
Debug.info(gRead.getDisplayObject().textfield.text);
}
]]></handler>
</canvas>
I found what is the problem. The problem is that i have to declare a variable and have to refer the property from that.
<canvas>
<library>
<text name="sample" id="gRead">
<method name="getTextFrom">
Debug.write("this.text" , this.sprite);
var mx = this.sprite;
Debug.write("this.text" , mx.textfield.text);
</method>
</text>
</library>
<handler name="oninit">
gRead.setAttribute('text',"HI");
gRead.getTextFrom();
</handler>
</canvas>

Migrating OpenLaszlo application to 5.0: The tag xxx cannot be used as a child of view

I want to know has anyone across a defect like this when upgrading open laszlo.
The tag xxx cannot be used as a child of view
The tag xxx cannot be used as a child of class
Why this error happens? Any Idea?
The error message xxx cannot be used as a child yyy of view simply means that you are using a tag inside a tag, and the child tag is not known. Simple example:
<canvas debug="true">
<view width="100" height="100" bgcolor="red">
<unknown_tag />
</view>
</canvas>
Compiler error message:
class_tag_error.lzx:4:48: The tag 'unknown_tag' cannot be used as a child of view
class_tag_error.lzx:5:20: Unknown tag
I remember that some people had a similar problem when upgrading from 4.0 to 4.2, here is the discussion in the laszlo-dev mailing list. Is the problem caused by a standard OpenLaszlo tag in your code, or by a custom class or tag you have added?
There is a schema file for all classes and tags the OpenLaszlo compiler knows, which can be found in
$LPS_HOME/WEB-INF/lps/schema/build/lfc.xml
If the compiler complains about a built-in LZX tag, you could - as a last resort - check that file if the class definition for that specific tag still exists in the OpenLaszlo version you are using. Here is - for example - the beginning of the class/interface definition for the <view> tag:
<interface extends="node" jsname="LzView" name="view">
<method args="who, self, prop, refView" name="$lzc$getAttributeRelative_dependencies"/>
<method args="who, self" name="$lzc$getBounds_dependencies"/>
<method args="who, self" name="$lzc$getCurrentTime_dependencies"/>
<method args="ignore" name="$lzc$getMouse_dependencies"/>
<method args="who, self" name="$lzc$getTotalTime_dependencies"/>
<method args="ignore" name="$lzc$isMouseOver_dependencies"/>
... (continued)
Although that's definitely not a comfortable way of finding out if a tag still exists.

Apache Tiles set html tag attribute using <put-attribute> value

I am using Apache Tiles 2.1 as my templating framework (along with Spring MVC).
I want to know how best to be able to set HTML attribute values from within my Tiles definitions file. For example I have a text box and want to be able to set the maxlength attribute from within my definition. I expected the following to work -
<input id="nameField" type="text"
maxlength="<tiles:insertAttribute name='maxlength' />" />
using this definition -
<definition name="sprint-goal" >
<put-attribute name="maxlength" value="100" />
</definition>
But it seems that Tiles ignores the <insertAttribute/> tag if placed within a HTML tag. It works fine otherwise.
Note: I have tried using a ViewPreparer to set request-scoped values. This will work but is not exactly what I am looking for. I would like to easily set HTML attribute values from within a Tiles definition.
To set the value of html element attributes, your best bet is to use Expression Language. First, expose the tile attribute as a java variable using the tiles useAttribute tag. Then use '${}' to print the variable.
Example:
<tiles:useAttribute name="myMaxLength" id="maxLength" />
<input id="nameField" type="text" maxlength="${myMaxLength}" />
More info:
- updated June 2014: https://tiles.apache.org/2.2/framework/tiles-jsp/tlddoc/tiles/useAttribute.html
- http://docs.oracle.com/javaee/1.4/tutorial/doc/JSPIntro7.html
<put-attribute name="maxlength" value="100" type="string" />
I type isn't defined as "string" it would be taken as a URL to include...