I'm triying to use a conditional #command with an argument passed with Executions.createComponents, this is my java code:
Map data = new HashMap();
data.put("isFromHere", true);
modal = (Window) Executions.createComponents("root/to/window", null, data);
modal.doModal();
And in my zul page I'm trying to do this:
<button label="Save" onClick="#command(arg.isFromHere ? 'save' : 'not')" />
But every time arg.isFromHere is returning false, like the argument is not passed. But if I do this:
<button if="${arg.isFromHere}" label="Save" onClick="#command('save'" />
That does work fine! What means the arguments are getting to the zul page, but not working on conditional commands, Is there a way to make it work?
It has all to do with the lifecycle of the binder.
#Command and ${arg.xxx} are on different lifecycle.
Read this documentation and see your solution in it.
Solution for you :
VM :
private boolean fromHere;
#Init
public void init(#ExecutionArgParam("isFromHere") boolean fromHere){
this.fromHere = fromHere;
}
public boolean isFromHere() {
return fromHere;
}
zul :
<button label="Save" onClick="#command(vm.fromHere ? 'save' : 'not')" />
Related
What I want to do is passing value from page1.zul to page2.zul through <include> and viewModel.
From page1.zul, I have
<include processId="#bind(vm.selectedProcess.id)" src="#load('page2.zul')"></include>
And then it should pass to a viewModel in page2.zul
#Init
public void init(#ExecutionArgParam("processId") String processId){
System.out.println("processInstanceId : " + processId);
}
However, I always get a null value. Any idea how to do this thing ? page2.zul looks something like this :
<div apply="org.zkoss.bind.BindComposer"
viewModel="#id('vm') #bind('com.mrye.viewModel')">
<label value="#load(vm.processId)"></label>
</div>
First of all, make distinguish names for Id's of the VM.
Then zul :
<div apply="org.zkoss.bind.BindComposer"
viewModel="#id('vm') #init('com.mrye.viewModel', processId = parentVM.selectedProcess.id )">
And VM2:
#Init
public void init (#BindingParam("processId") MyObject processID) {
Edit after the comment :
As you can see in this fiddle it works, but your parameter has to be initialized.
If you want to have "live data" passed to other zul (not other viewmodel), you can use #ref or just use parentVM.
If the live data need's to be in the viewmodel itself, you can use a non visible textbox where you load the data from parentVM and save it in the includedVM just before some action happens.
See updated fiddle here.
Here you can check
Index.zul
<?page title="URL Parameters Test" contentType="text/html;charset=UTF-8"?>
<zk>
<window title="URL Parameters Test" border="normal">
<include src="header.zul?test=5" />
</window>
</zk>
In above code you can check it pass argument with URL here test is argument name and value=5
<?page contentType="text/html;charset=UTF-8"?>
<zk>
<window border="none" width="100%" height="100%" apply="pkg$.HeaderComposer">
<label id="lblHeader" />
<div>
Load from EL [ <label value="${param.test}" />]
</div>
</window>
</zk>
In this page we used ${param.test} to get the parameter passed in index.zul , HeaderComposer.java
import org.zkoss.zk.ui.*;
import org.zkoss.zk.ui.event.*;
import org.zkoss.zk.ui.util.*;
import org.zkoss.zk.ui.ext.*;
import org.zkoss.zk.au.*;
import org.zkoss.zk.au.out.*;
import org.zkoss.zul.*;
public class HeaderComposer extends GenericForwardComposer{
Label lblHeader;
#Override
public void doAfterCompose(Component comp) throws Exception {
try {
super.doAfterCompose(comp);
}
catch (Exception e) {
e.printStackTrace();
}
/*
* retrieve url parameters
*/
String[] parameter = (String[]) param.get("test");
if (parameter != null)
lblHeader.setValue( "Congratulations! Your parameters value is " + parameter[0] );
else
lblHeader.setValue( "No parameters found. URL should be something like http://yourserver/yoursite/main.zul?parameter=param-value" );
}
}
for more way you can check http://zkframeworkhint.blogspot.in/2014/05/zk-include-how-to-pass-and-get.html
Just be sure on VM1 the value vm.selectedProcess.id is correctly initialized and it has a value, in the VM2 add the #AfterCompose lifecycle annotation then on #Init get the value, according to your code this should work on VM2:
Long processId;
#AfterCompose
public void initAfterCompose(#ContextParam(ContextType.VIEW) Component view) {
Selectors.wireComponents(view, this, false);
}
#Init
public void init() {
//get dynamic attribut
processId = (Long) Executions.getCurrent().getAttribute("processId");
}
I'm inexperienced, especially at MVVM, but trying to use ReactiveUI, and I'm not understanding the examples that I'm finding that demonstrate ReactiveCommand. I have used ICommand / DelegateCommand one time before, but this is different, and I'm not getting it.
What I'm trying to do is really simple. Click a button in the view, and have that execute a method in the view model. The examples that I'm finding all involve IObservable<>, and I don't get that, as they don't explanations that are geared to the total noob that I am.
Basically, I'm trying to use this as a learning experience, and what I'd ideally like to do is bind the button's Command property in xaml to a command (however that works, I don't know), which causes a method to execute. No collections, I'd just be passing a single int variable.
Thanks for the help. I really appreciate it.
Edit - Below appears code using Paul Betts' suggestions:
C#
public ReactiveCommand AddToDailyUsed { get; protected set; }
public MainPageVM()
{
Initialize();
AddToDailyUsed = new ReactiveCommand();
AddToDailyUsed.Subscribe(AddToTodayUsedAction => this.AddToDailyUsedExecuted());
}
private object AddToDailyUsedExecuted()
{
MessageBox.Show("AddToDailyUsedAction");
return null;
}
private void AddToDailyUsedAction(object obj)
{
MessageBox.Show("AddToDailyUsedAction");
}
XAML
<Button Content="{Binding Strings.add, Source={StaticResource LocalStrings}}"
Command="{Binding AddToTodayUsed}"
Margin="-5,-10, -10,-10"
Grid.Row="3"
Grid.Column="2" />
Obviously I'm missing something. I inserted break points at the AddToDailyUsedExecuted and AddToDailyUsedAction methods, and they are never reached.
Edit Constructor for code behind the view:
MainPageVM mainPageVM = new MainPageVM();
public MainPage()
{
InitializeComponent();
Speech.Initialize();
DataContext = mainPageVM;
ApplicationBar = new ApplicationBar();
TaskRegistration.RegisterScheduledTask();
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
//Shows the rate reminder message, according to the settings of the RateReminder.
(App.Current as App).rateReminder.Notify();
}
So, ReactiveCommand is itself an IObservable<object> - in this case, you can conceptualize IObservable as an Event - this Event fires when the command is invoked (i.e. when the button is pressed). So, in your constructor, you might write:
MyCommand = new ReactiveCommand();
MyCommand.Subscribe(param => this.MyCommandHasExecuted());
However, what's neat about IObservable that isn't true about regular events, is that you can use LINQ on them:
// Now, MyCommandHasExecuted only gets run when the UserName isn't null
MyCommand.Where(param => this.UserName != null)
.Subscribe(param => this.MyCommandHasExecuted());
Update: Your Xaml binds to AddToTodayUsed but your ViewModel command is called AddToDailyUsed. Could that be it?
I will like to edit a list of items in the same page. Each item should be edited using a separate form. I am creating a h:form within ui:repeat. Only when the last form is submitted, the user input is applied to the managed bean. For all other forms, user input is not applied to the model.
#ManagedBean
public class Controller {
Logger logger = Logger.getLogger("TestWeb");
private List<Customer> customerList;
public List<Customer> getCustomerList() {
if (customerList == null) {
customerList = new ArrayList<Customer>();
customerList.add(new Customer("Daffy Duck", "daffy#example.com"));
customerList.add(new Customer("Bugs Bunny", "bugs#example.com"));
customerList.add(new Customer("Samity Sam", "sam#example.com"));
}
return customerList;
}
public String updateCustomer(Customer c) {
logger.info("Updating: " + c.getName());
return null;
}
}
In the view, I have
<ui:repeat var="c" value="#{controller.customerList}">
<h:form>
<h3>Edit Customer</h3>
Name: <h:inputText value="#{c.name}"/><br/>
E-mail: <h:inputText value="#{c.email}"/><br/>
<h:commandButton value="Update"
action="#{controller.updateCustomer(c)}"/>
</h:form>
</ui:repeat>
I search for hours without any solution. What will be the correct way to do this? I can hack it by using a single form and using a ui:repeat within it. But there are many issues with that and I will rather not take that route. Thanks.
This is a bug in state saving of <ui:repeat> in Mojarra. There are several similar issue reports at http://java.net/jira/browse/JAVASERVERFACES, among others issue 2243.
You have basically 2 options: use another iterating component (e.g. <c:forEach>, <h:dataTable>, <t:dataList>, <p:dataList>, etc), or replace Mojarra by MyFaces (the <ui:repeat> in this construct works properly in there).
I'm dynamically adding textboxes to a form on my jsp page using Javascript. When that form is submitted to an action, how does my action get the values of those textboxes? (I'm using Struts 2, btw.) In ASP.NET, I was able to find them in Form.Request/FormCollection. Is there a Struts 2 equivalent? Thanks a million.
In Struts2, you create beans in the form to do submit values. In order to create the input text-box, use the <s> tag. For example :
<s:textfield name="loginBean.userName" label="UserName" required="true" />
Here loginBean is the bean passed to the jsp page when.
Bean consists of variable declarations and getters-setters for the variable.
Then in the back-end Java where the form is submitted to, you can access the same bean.
Declare getter-setter in Java and then you can access the properties of the bean.
public LoginBean getLoginBean() {
return loginBean;
}
public void setLoginBean(LoginBean loginBean) {
this.loginBean = loginBean;
}
public String authenticate() {
String username = loginBean.getUserName();
I would recommend looking at source codes of open-source Struts projects.
It sounds like you're trying to populate a dynamic list. To do that, you just have to use the [n] index syntax at the end of your Action class property name:
HTML:
<input type="text" name="yourCollection[0]" value="first value" />
<input type="text" name="yourCollection[1]" value="second value" />
<input type="text" name="yourCollection[2]" value="third value" />
Action Class:
public class YourAction extends Action {
public List<String> yourCollection;
public List<String> getYourCollection(){
return yourCollection;
}
public void setYourCollection(List<String> aCollection){
this.yourCollection = aCollection;
}
}
I have following UI part on JSF - it's simple search form with input field and submit:
<h:form>
<h:commandButton action="#{operation.found}" value="#{msg.search}" />
<h:inputText name="searchParam"/>
</h:form>
And correspondingly, on backend, i attempt to get value of input field next way:
public List<Store> getFound() {
String name = (String) FacesContext.getCurrentInstance()
.getExternalContext().getRequestParameterMap().get(
"searchParam");
SessionFactory sessionFactory = new Configuration().configure()
.buildSessionFactory();
HibernateTemplate hbt = new HibernateTemplate();
hbt.setSessionFactory(sessionFactory);
foundStores = hbt.find(BEAN_PATH + " WHERE name = ?",
new Object[] { name });
return foundStores;
}
And null name is passed to backend.
It seems that problem in .jsf part, but from first glance looks ok...
You must point the <h:inputText> to a managed-bean property:
<h:inputText name="searchParam" value="#{searchBean.searchParam}" />
and define in your bean:
private String searchParam;
public String getSearchParam() {..}
public void setSearchParam(String searchParam) {..}
and then use the searchParam in your getFound() method;
Of course, you need to have the bean defined as managed bean, but I assume you have done it:
<managed-bean>
<managed-bean-name>searchBean</managed-bean-name>
<managed-bean-class>mypackage.SearchBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
You can check a JSF tutorial (like this, for example)