I am developing ZK application, which contains few roles. For role "Guest" I have to to make all components in readonly mode. So how to create a container ( Window Div Layout) in readonly mode in ZK application ?
问题:
回答1:
Yes you can do this in MVVM also.
So let's start with the beginning.
You need to wire some components as in the answer you reffering :
@Wire("disable")
private List<Disable> allToDisable;
private boolean disable;
The second thing is, implementing the AfterCompose for disabling and the Init for checking the status.
In normal MVVM you almost never need to use the @AfterCompose
but when you need to wire for solutions like this, you will need it.
@Init
public void init() {
disable = checkForGuest();
}
/**
* This method will launch when all components are created.
* @param view to wire the components
*/
@AfterCompose
public void afterCompose(@ContextParam(ContextType.VIEW) Component view) {
Selectors.wireComponents(view, this, false); // after this your private fields are wired.
disableAll(disable);
}
private void disableAll(boolean disableStatus){
for(Disable d : allToDisable) {
d.setDisabled(disableStatus);
}
}
What you need to know is that @Init is triggered first and after that the AfterCompose is triggered.
Edit:
That's because the databinding happens after the @AfterCompose
.
You could add a getter for the disable
and the the zul :
<checkbox disabled="@load(yourValue or vm.disabled)"/>
With this, if 1 of the 2 is true, the checkbox is always disabled.
Last edit :
While going home from work, I can't let this go like this without a descend solution.
After a good night rest, I have found the solution for you.
@AfterCompose
public void afterCompose(@SelectorParam("*") Collection<Component> allToDisable, @ContextParam(ContextType.BINDER)Binder binder) {
for(Component comp : allToDisable) {
if (comp instanceof Disable) {
((Disable)comp).setDisabled(disable);
binder.removeBindings(comp, "disabled");
}
}
}
**Explication : **
While yesterday I didn't test if the @Wire("disable")
worked or not, I'm not getting that working in ZK Fiddle.
So first of all, I wanted to get rid of the @Wire
so we use the @SelectorParam
to do the same and like this we don't need to call the Selectors
.
I had the same problem using @Wire
or with @SelectorParam
that I never had any component in the List.
So now, we just get every component in the view and check if it is an instance of the Disable
interface, witch is actually the same, like this you could even say not for buttons.
Then the second thing, is just removing the binding of the attribute disabled
for that Component.
You can do that, by asking the Binder
from the context with the @ContextParam
annotation.
At last, we remove the binding by binder.removeBindings(Component, String);
.
Watch out, not to remove the complete binding with binder.removeBindings(Component);
because at that moment your bindings for the values are also gone.
You can check it out in this fiddle (I exclude the button by checking for Textbox
so you could still press the button)
回答2:
A container is not the correct place to set the enabled/disabled property. It's a "passive" element containing all sorts of other components.
To enable/disable input, you have to set the property directly at the input components like textbox
, combobox
, ... . They usualy have a disabled
property which has to be set to true
if the client is in read only mode.
When using MVVM you can shortcut this by binding the disabled property of all components to the same view model property:
<zk>
<window title="Enable/Disable" border="normal" width="600px"
apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('pkg$.TestVM')" >
<hbox>
<vbox>
<checkbox label='readonly' checked='@bind(vm.readonly)' />
</vbox>
<div>
<textbox value='test' disabled='@bind(vm.readonly)' />
<checkbox label='test' disabled='@bind(vm.readonly)' />
</div>
</hbox>
</window>
</zk>
Here you can find a working example fiddle.