In the example below, the converter works correctly when the form is submitted. However, when attempting to perform any actions in the event 'onchange', the value of type 'enum' is changed to null. After several attempts and research, using valueChangeListener, onchange = "submit()" and immediate = "true", nothing resolved.
Enum
public enum TipoGasCondicaoUsoPermeacao {
CONCENTRACOES("Concentrações"),
FUGACIDADES("Fugacidades"),
PRESSOES_PARCIAIS("Pressões parciais");
private String label;
private TipoGasCondicaoUsoPermeacao(String label) {
this.label = label;
}
/**
* #return the descricao
*/
public String getLabel() {
return this.label;
}
}
XHTML
<h:selectOneMenu value="#{condicaoUso.tipoGasCondicao}" required="false" styleClass="field_form medio">
<f:selectItems value="#{listaMB.tiposGasCondicoesUso}" id="itemTipoGas" />
<a4j:support event="onchange" oncomplete="dadosAlterados(true)" reRender="otherPanel" />
</h:selectOneMenu>
faces-config.xml
<converter>
<converter-for-class>java.lang.Enum</converter-for-class>
<converter-class>javax.faces.convert.EnumConverter</converter-class>
</converter>
The problem persisted until I used the property ajaxSingle="true" (default is 'false'), as shown below:
<a4j:support event="onchange" oncomplete="dadosAlterados(true)" reRender="otherPanel" ajaxSingle="true" />
Magic?
Related
I am trying to get a subclass of the Xamarin Forms "Label" class. In my subclass, among a lot of other changes, I want to have a different default value for some bindable properties (such as FontSize and FontAttributes). However, if I set these in the constructor, it seems that Style specifiers won't override these, presumably because the bindings are already noticing that they are using non-default values. Is there a way to specify in a subclass that you want to use different default values in a bindable property?
class MyCustomLabel : Label {
public MyCustomLabel() {
FontSize=20;
}
}
<ResourceDictionary>
<Style x:Key="Superbig" TargetType="MyCustomLabel">
<Setter Property="FontSize" Value="3" />
</Style>
</ResourceDictionary>
<MyCustomLabel Style="{StaticResource Superbig}" Text="Hi There!" />
Here, the Superbig style is not being applied because I am setting the new default value in the constructor. Therefore, I was hoping either (a) there was some other way to set a new default value, or (b) there was some other way to set a style so it overrode any value that was already set.
Unfortunately, BindableProperty doesn't seem to support OverrideMetadata like DependencyProperty does. Here's two way to achieve this.
1) Set a default Style for your MyCustomLabel object (XAML)
<ResourceDictionary>
<!--Default style-->
<Style TargetType="local:MyCustomLabel">
<Setter Property="FontSize" Value="10" />
</Style>
<!--Superbig style-->
<Style x:Key="Superbig" TargetType="local:MyCustomLabel">
<Setter Property="FontSize" Value="40" />
</Style>
</ResourceDictionary>
2) Create a new FontSize BindableProperty (C#)
public class MyCustomLabel : Label
{
public MyCustomLabel()
{
base.SetBinding(Label.FontSizeProperty, new Binding(nameof(FontSize))
{
Source = this,
Mode = BindingMode.OneWay
});
}
//Don't forget the "new" keyword
public new double FontSize
{
get { return (double)GetValue(FontSizeProperty); }
set { SetValue(FontSizeProperty, value); }
}
//Don't forget the "new" keyword
public static readonly new BindableProperty FontSizeProperty =
BindableProperty.Create(nameof(FontSize), typeof(double), typeof(MyCustomLabel), 40.0);
}
i have a for each in my zk page, and in the each i am creating a column, and in my column i need add a iframe, and to each frame i need pass as variable the label of the column.
I have something like:
<zk>
<window title="Dynamic Columns" border="normal" width="1824px" apply="org.zkoss.bind.BindComposer" viewModel="#id('vm') #init('pkg$.DynamicColumnModel')">
<grid >
<columns>
<column forEach="${vm.columnList}" label="${each}">
<iframe
src="test.zul" />
</column>
</columns>
</grid>
</window>
</zk>
But i have an error when i include the page, and my first problem is that i do not know how can i pass a variable to each iframe.
And my java is something like:
public class DynamicColumnModel {
private List<String> columnList = new ArrayList<String>();
private String texto="123";
#Init
public void init(){
columnList.add("Dynamic Col A");
columnList.add("Dynamic Col B");
columnList.add("Dynamic Col C");
columnList.add("Dynamic Col D");
}
public List<String> getColumnList() {
return columnList;
}
public void setColumnList(List<String> columnList) {
this.columnList = columnList;
}
public String getTexto() {
return texto;
}
public void setTexto(String texto) {
this.texto = texto;
}
#Command
public void mensaje(){
}
}
Thanks
If your each is a String, which it appears to be as you set it as the column label, just go ahead and pass it as a URL parameter to the iframe.
<window apply="org.zkoss.bind.BindComposer"
viewModel="#id('vm') #init('pkg$.DynamicColumnModel')">
<grid >
<columns>
<column forEach="${vm.columnList}" label="${each}">
<iframe src="test.zul?myValue=${each}" />
</column>
</columns>
</grid>
</window>
Note that when you are using an iframe component, you are stepping outside ZK. True, the iframe itself points to a ZK page, but it's a not within the same ZK environment. The iframe could just as easily include www.google.com and so there is no specific ZK support for passing values to ZK pages included in this manner.
If you're only including ZK pages and want to pass information to these pages more fluidly, you'll want to use ZK's include tag. Have a look at the documentation on how to pass values to included ZK pages.
Edit
If going the iframe route, you can access URL parameter values from test.zul using ZK's Execution class:
Execution execution = Executions.getCurrent();
execution.getParameter("myValue");
So I have set up a wizard interface with spring web flow that gradually populates a single form object/model. It works fine for the first few steps that have to populate single String or primitive properties and a String array (from a checkbox interface).
Then I have a List<String> property. It renders properly as multiple textboxes with correct initialized values. But when I edit the textboxes on the browser and submit, the values do not take effect on the form bean. It still has the initial values.
Below is the detailed set-up:
Web flow on-start which creates the bean:
<on-start>
<evaluate expression="new mypackage.MyFormBean()" result="flowScope.myFormBean" />
</on-start>
Here are the relevant parts of my form bean:
public class MyFormBean implements Serializable {
...
private List<SlotBean> slots;
...
public List<SlotBean> getSlots() {
return slots;
}
public void setSlots(List<SlotBean> slots) {
this.slots= slots;
}
...
}
public class SlotBean {
...
private int quantity;
...
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity= quantity;
}
...
}
I have a series of view-states in my web flow with simple string or number field bindings set-up that are initialized, displayed and saved without issues to the form.
This view-state generates any number of SlotBean objects then initializes quantity with 2. These are set to the slots property.
<view-state id="generate-criteria" model="disciplineCatalogue">
...
<transition on="next" to="slots-grid">
<evaluate expression="myService.generateSlots(myFormBean)"/>
</transition>
...
</view-state>
Here is the jsp fragment. All it does is render a bunch of textboxes. There's also a next button:
<form:form id="slotsGrid" modelAttribute="myFormBean" action="${flowExecutionUrl}">
...
<c:forEach var="slot" items="${myFormBean.slots}" varStatus="idx">
<form:input path="slots[${idx.index}].quantity" />
</c:forEach>
...
<button type="submit" id="next" name="_eventId_next">Next</button>
...
</form:form>
The above code displays correctly with the initial values (2). It generates multiple textboxes like below:
<input id="slots0.quantity" name="slots[0].quantity" type="text" value="2"/>
So when this page is on the browser, I change the values of the quantity textboxes to different values and click the "next" button. On my browser's network debugger, I see that the form values are sent to the server:
slots[0].quantity:3
slots[1].quantity:1
slots[2].quantity:2
Here is the relevant web flow entry for the next button.
<view-state id="slots-grid" model="myFormBean">
<binder>
...
<binding property="slots" />
</binder>
...
<transition on="next" to="finished">
<evaluate expression="myService.create(myFormBean)"/>
</transition>
...
</view-state>
So I put a break point on the myService.create(myFormBean) method and it shows that all the quantity fields are still set to the original "2". The new values didn't bind to myFormBean.slots.
Is there anything you can see in my set-up that looks wrong?
Thanks for any time you can put into this
Spring Framework 3.1.1
Spring-Webflow 2.3.1
Tomcat 6.0.18
Eclipse Indigo
Cross-posted in:
http://forum.springsource.org/showthread.php?127809-Collection-List-property-won-t-bind-or-update-on-form-submit
In my example below I have several objects. I want to change the label of all objects in one go, without calling each element by id. I know how to do this in HTML, but not in Flex.
// HTML
<div class="text" id="text1">SomeText</div>
<div class="text" id="text2">SomeText</div>
<div class="text" id="text3">SomeText</div>
// jQuery
$(".text").css("color", "#333333");
This is how I would usually set the color of 3 objects to grey in one line.
// Flex
<s:Button id="button1" label="Button 1"/>
<s:Button id="button2" label="Button 2"/>
<s:Button id="button3" label="Button 3"/>
// AS3
button1.label = 'Something else';
button2.label = 'Something else';
button3.label = 'Something else';
Is there any way I can change the labels of all 3 buttons with a single line of code similar to the jQuery example? Thanks in advance.
I'm pretty sure the answer is no, with a caveat.
Keep in mind that JQuery is a framework that hides the complexity of what it is doing. ( A lot of frameworks do that including the flex Framework ). In Flex, I can create a DataGrid in one line of code. However, there are thousands of lines of code, and multiple classes already written that allow me to do that. I suspect the same is true for a lot of JQuery functionality.
there is no reason you can't encapsulate that functionality to make the change and then call it with one line of code.
As #www.Flextras.com pointed out - you can write a class to do this.
I'd encourage you to consider an alternative approach however, as looping through the children looking for a specific property is quite slow. That said - it does make for an interesting coding challenge.
Here's a class & example that should acheive what you're after.
package com.mangofactory.util
{
import flash.display.DisplayObject;
import mx.core.UIComponent;
/**
* Utility class to set a given property of all matching children on a target.
* Named to act as an operator, rather than a class (hence no captial letter)
*
* eg., on(someTarget).of(SomeClass).someProperty = someValue;
* */
public class on
{
private var root:UIComponent;
private var requiredPropertyName:String;
private var requiredType:Class;
public function on(root:UIComponent)
{
this.root = root;
}
/**
* Returns a list of targets which match the defined criteria.
* Note - the root component is also evaluated
* */
private function get targets():void
{
var result:Array = [];
if (matches(root))
{
result.push(root);
}
for (var i:int = 0; i < root.numChildren; i++)
{
var child:DisplayObject = root.getChildAt(i);
if (matches(child))
result.push(child);
}
}
/**
* Returns true if the target param matches the defined criteria.
* If a propertyName has been given (by calling 'having') that is checked first.
* Otherwise, the type is checked against the value passed calling ('of')
* */
private function matches(target:Object):Boolean
{
if (requiredPropertyName && target.hasOwnProperty(requiredPropertyName))
return true;
if (requiredType && target is requiredType)
return true;
return false;
}
public function having(propertyName:String):PropertyCatcher
{
this.requiredPropertyName = propertyName;
}
public function setOnTargets(propertyName:*,value:*):void
{
for each (var matchedTarget:Object in targets)
{
if (matchedTarget.hasOwnProperty(propertyName))
matchedTarget[propertyName] = value;
}
}
public function of(type:Class):PropertyCatcher
{
this.requiredType = type;
}
}
}
import com.mangofactory.util.on;
import flash.utils.Proxy;
import flash.utils.flash_proxy;
use namespace flash_proxy;
dynamic class PropertyCatcher() extends Proxy
{
private var callbackTarget:on;
public function PropertyCatcher(callbackTarget:on)
{
this.callbackTarget = callbackTarget;
}
override flash_proxy function setProperty(name:*, value:*):void {
callbackTarget.setOnTargets(name,value);
}
}
And an example:
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<s:Button />
<s:Button />
<s:Button />
<mx:Canvas />
<fx:Script>
<![CDATA[
public function doTest():void
{
// Sets the label of all Buttons to "Hello World"
on(this).of(Button).label = "Hello World";
// Sets the visible property of all children which declare a "alpha" property to false.
on(this).having("alpha").visible = false;
}
]]>
</fx:Script>
</mx:Canvas>
Note - I haven't tested this, but in theory it should work.
I don't know of any selector of the css3/jquery type for flex. But a workaround will be to use an array of buttons instead of many buttons variables and then just iterate through all of them (button[i] instead of buttoni)
I want to perform simple validation against multiple fields. Please note these fields are not within a mx:Form since the way they are displayed isn't the norm. The validation works properly, however, it does not highlight the textInput with the error message.
myValidator.source = empName1;
myValidator.property = "text";
if(myValidator.validate().type == ValidationResultEvent.VALID)
{
Alert.show("good");
}
...
<mx:StringValidator id="myValidator" required="true" minLength="1" requiredFieldError="This field is required" />
<mx:TextInput x="152" y="32" width="207" id="empName1"/>
Please note I want to use the same validator "myValidator" against multiple fields which is why the source and property are set in the actionscript 3 code.
Thanks
Update:
heres a similar function I created that works:
private function validateField(fields:Array):Boolean
{
var rtnResult:Boolean = true;
for each(var i:Object in fields)
{
myValidator.source = i;
myValidator.property = "text";
i.validateNow();
if(myValidator.validate().type == ValidationResultEvent.INVALID)
rtnResult = false;
}
return rtnResult;
}
which is called like so:
if(!validateField([TicketTitle,TicketDesc]))
{
Alert.show("Required fields were left blank!", "Warning");
return;
}
and the mxml validator
<mx:StringValidator id="myValidator" required="true" minLength="1" requiredFieldError="This field is required" />
Solved it... I needed this:
empName1.validateNow();