ZK Listbox - OnClickListener -> SelectedIndex - listbox

Is it possible to implement an OnClick listener in a list box in ZK? The trigger when clicking on an item works fine with the following code, but I can't get to the clicked item (getSelectedItems () shows the items selected by checkbox or the topmost selected item, but I want to trigger something independent of it by clicking on it). That's why the OnSelect listener doesn't matter to me either, the checkbox element must be selected directly and is not automatically selected by clicking on the item.
Thanks for any hint.
ZUL:
<row>
<listbox id="article_output" width="100%" height=""
multiple="true" checkmark="true" nonselectableTags="*">
<listhead>
<listheader label="Article"/>
</listhead>
</listbox>
</row>
Create Model and Listener
public void fillListBoxWithArticles(final Listbox lb, List<Article> articles) {
lb.setItemRenderer(new ArticleItemRenderer());
lb.setCheckmark(true);
lb.setMultiple(true);
ListModelList<Article> lml_articles = new ListModelList<Article>(articles);
lml_articles.setMultiple(true);
lb.setModel(lml_articles);
lb.addEventListener(Events.ON_CLICK, new EventListener() {
#Override
public void onEvent(Event event) throws Exception {
logger.debug("SELECTED INDEX: " + lb.getSelectedIndex());
setArticleToInfobox(articles.get(lb.getSelectedIndex()));
}});
lb.focus();
}
ItemRenderer:
public class ArticleItemRenderer implements ListitemRenderer<Article> {
#Override
public void render(Listitem item, Article data, int index) throws Exception {
item.appendChild(new Listcell(data.getArticletitle())); }}

Related

How to add / bind multiple form values to server side blazor method

I try to expand the server side blazor todo app.
I would like to
add a responsible person to a todoitem
add a todoitem after onkeyup inside the input field
This gist contains my attempt to expand the todo app
What works
Adding a list of people inside a select field
<select>
#foreach (var person in people)
{
<option value="person">#person</option>
}
</select>
What does not work
Two things are not working
adding a person to a todoItem inside AddTodo()
adding a todoItem for the event onKeyUp == Enter
The method
private void AddTodo()
{
if (!string.IsNullOrWhiteSpace(newTodo))
{
todos.Add(new TodoItem { Title = newTodo, Responsible = person});
newTodo = string.Empty;
}
}
Questions
How can multiple form values (input, select) be bound to a method?
Why is onkeyup not firing?
Source code of my Todo.razor gist
The cause for why is onkeyup not firing? was a silly mistake; the event handler was attached to the wrong input. This seems to work
<input placeholder="Something todo" #bind="newTodo" #onkeyup="AddTodoOnEnter" />
To get a value from a selected option from a select-tag to your code you bind the variable #newPerson on the select-tag.
<select #bind="newPerson">
#foreach (var person in people)
{
<option value="#person" >#person.name (#person.id)</option>
}
</select>
You can access it inside the #code section with
#code {
// named tuple list
private List<(int id, string name)> people = new List<(int id, string name)>()
{
(1, "Tom"), (2, "Luise"), (3,"Jane")
};
private void AddTodo()
{
if (!string.IsNullOrWhiteSpace(newTodo))
{
todos.Add(new TodoItem { Title = newTodo, Responsible = "who " + newPerson });
newTodo = string.Empty;
}
}
Screenshot of the html
Current Code / Gist
I updated my gist - you can see the old code next the revision 4 side by side here

How to send clicked item as parameter in an ListView item binding

I have a dynamic list and it is the source of a ListView.
I have a command in the ViewModel, where I need to receive the item, which was clicked. I want to get the object that represents that item, so I can perform a change on it.
I am using MvvmCross.
That is fairly trivial. I imagine you have a ListView in your layout which looks something like:
<Mvx.MvxListView
...
local:MvxBind="ItemsSource Items" />
To be able to get the clicked item you just add a command to ItemClick:
<Mvx.MvxListView
...
local:MvxBind="ItemsSource Items; ItemClick ItemClickedCommand" />
Then in your ViewModel you should have an ItemClickedCommand:
private MvxCommand<ItemViewModel> _itemClickedCommand;
public ICommand ItemClickedCommand
{
get
{
return _itemClickedCommand = _itemClickedCommand ??
new MvxCommand<ItemViewModel>(item => {
// do something with the item here
}):
}
}
Where ItemViewModel is the type of the items in the collection you have bound to the ItemsSource.

how to get which tab is clicked when accordion is loaded intially on a page

I have an accordion panel with tabs containing name of students. I select on one of the tab and choose edit. I am calling a tab change listener and getting student object and trying to edit it works fine.
But My problem is when for the first time Accordion loads, even though I select on the tab,and click on edit, I will get not get student object. Its giving me null pointer exception. since Tab change event does not get called for the first time it loads. How do I solve this?
private StudBean formBean;
public StudBean getFormBean() {
if(formBean==null){
formBean= new StudBean();
}
return formBean;
}
public void onTabChange(TabChangeEvent event) {
formBean = (StudBean) event.getData();
}
public String edit(){
formBean = testDelegate.getDetails(formBean.getName(),formBean.getId());
return "/ui/EditStudent?faces-redirect=true";
}
<p:commandButton process="#this" value="edit" action="#{testBean.edit}" >
<p:accordionPanel value="#{testBean.students}" var="stud">
<p:ajax event="tabChange" listener="#{testBean.onTabChange}" immediate="true"/>
<p:tab title="#{stud.name}">

How tos set active index of tabview to zero only after calling a tabview change listener

<p:tabView widgetVar="addSystemWizard" style="width:980px;height:400px;" dynamic="true" activeIndex="#{testBean.messagesTab.activeIndex}" >
<p:ajax event="tabChange" listener="#{testBean.onTabChange}" update=":tabview:sysMsg"/>
<p:tab id="generalInfo" title="1. General Information"> `enter code here`
private TabView messagesTab;
public TabView getMessagesTab () {
if(messagesTab==null){
messagesTab= new TabView();
}
return messagesTab;
}
public void setMessagesTab(TabView messagesTab ) {
this.messagesTab = messagesTab;
}
public void onTabChange(TabChangeEvent event){
if(test.getName()==null || test.getName().equals("")){
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, event.getTab().getId() ,"please enter all required fields");
FacesContext.getCurrentInstance().addMessage(null, msg);
int idx=0;
messagesTab= (TabView) event.getComponent();
messagesTab.setActiveIndex(idx);
}
}
I am calling a tabchange event on tabview, I have name attribute im my page,if that attribute is blank or null I have to stay on same tab, otherwise I ahve to go next tab, basically performing validation.. I have posted the above code to do that, but its not working!
I found this blog post that describes how to use a p:remoteCommand and javascript to accomplish this.
Trying various approaches to the question above (with p:ajax event="tabChange" and so on), I came up with a clean and well working solution. The code below turns on the PrimeFaces TabView into a "wizard mode". That means, the user stays on the same tab when he / she is trying to switch tabs and has validation errors within the current tab. The main idea is to use p:remoteCommand for a deferred decision about tab switching. If no validation errors were present, the switching occurs by the TabView widget's method select.
XHTML:
<p:tabView ... widgetVar="tv_widget" styleClass="tv_selector">
...
</p:tabView>
<p:remoteCommand name="tv_remoteCommand" process="#(.tv_selector)" update="#(.tv_selector)" global="false"
oncomplete="handleTabChangeTV(xhr, status, args, tv_widget)"/>
<h:panelGroup id="tv_script" styleClass="tv_selector">
<script type="text/javascript">
$(function(){
bindOnClickTV(tv_remoteCommand, tv_widget);
});
</script>
</h:panelGroup>
Javascript:
function bindOnClickTV(rc, widget) {
// unbind PrimeFaces click handler and bind our own
widget.jq.find('.ui-tabs-nav > li').unbind('click.tabview').
off('click.custom-tabview').on('click.custom-tabview', function (e) {
var element = $(this);
if ($(e.target).is(':not(.ui-icon-close)')) {
var index = element.index();
if (!element.hasClass('ui-state-disabled') && index != widget.cfg.selected) {
// buffer clicked tab
widget.clickedTab = element.index();
// call remote command
rc();
}
}
e.preventDefault();
});
}
function handleTabChangeTV(xhr, status, args, widget) {
if (!args.validationFailed) {
widget.select(widget.clickedTab);
}
}

How to pass JSF variable to jQuery

Suppose i have JSF page
<h:body>
<h:form id="formID" prependId="false">
<h:outputText id="randomID" value="#{randomNumber.random}"/>
<h:commandButton id="buttonID"
value="Random"
onclick="myArrayList(countries)" /> //just example
</h:form>
</h:body>
#ViewScoped
public class RandomNumber {
private int totalCountries;
private String data = "Afghanistan, Albania, Zimbabwe";
private List<String> countries;
public RandomNumber() {
countries = new ArrayList<String>();
StringTokenizer st = new StringTokenizer(data, ",");
while(st.hasMoreTokens()) {
countries.add(st.nextToken().trim());
}
totalCountries = countries.size();
} //end of constructor
} //end of class RandomNumber
.js file
function myArrayList(countries) {
.....
}
See when user click on button then i want to call Jquery function whom i am passing my ArrayList. Is it possible to pass your current JSF variable with values to javascript or jQuery?
Thanks
EDIT
**_________________________________________________-*
<h:body>
<h:form id="formID" prependId="false">
<h:outputText id="countries" value="#{countries.countries}" style="display:none"/>
<h:inputHidden id="hiddenCountries" value="#{countries.countries}" />
<h:commandButton id="buttonID"
value="Random"
onclick="myArrayList()"/>
</h:form>
</h:body>
#ViewScoped
public class Countries {
private int totalCountries;
private String data = "Afghanistan, Albania, Zimbabwe";
private List<String> countries;
/** Creates a new instance of Countries */
public Countries() {
countries = new ArrayList<String>();
StringTokenizer st = new StringTokenizer(data, ",");
while(st.hasMoreTokens()) {
countries.add(st.nextToken().trim());
}
totalCountries = countries.size();
} //end of constructor
public List<String> getCountries() {
return countries;
}
public void setCountries(List<String> countries) {
this.countries = countries;
}
} //end of class Countries
function myArrayList() {
alert(jQuery('#countries').html());
alert(jQuery('#hiddenCountries').val()) //when using h:inputHidden
} //end of function myArrayList
You can do
<h:inputHidden id="someID" value="#{randomNumber.data}/>
(dont forget to added getter/setter to your data in the bean )
change your onclick of the h:commandButton
onclick="myArrayList()" // or onclick="myArrayList(#{SomeELExpressioGoesHere})"
change your js function into
function myArrayList(inputParam) {
alert(jQuery('#someID').val());
var yourJSString = jQuery('#someID').val();
var myArray = yourJSString.split(','); //when string is Afghanistan,Albania,Zimbabwe (no spaces)
alert(myArray[inputParam]);
}
in order to transfer your js string into array just use
var yourJSString = jQuery('#someID').val()
var myArray = yourJSString.split(','); //when string is Afghanistan,Albania,Zimbabwe (no spaces)
you might be needed to change someID into other id selector if you wont set prependId=false in your form... or simply use a broaded jquery selector like
alert(('input[id$="someID"]').val());
EDIT
Look at my example , you should work with your String data variable and not the countries , cause you should pass the data as string only and not as array... after you will pass the data variable to js you can manipulate it with simple slpit js function to make it back an array in your js... you are getting Conversion Error setting value '[Afghanistan, Albania, Zimbabwe]' for 'null cause you are trying to set String into array... probably the getter of countries converted implicitly the java array into string and when you try to submit it back (string into array) you getting the exception
in order to set from js back to to bean :
jQuery('#someID').val("Some new String goes here");
then when you will submit the form.. the value will be set back to server

Resources