I'm trying to use jQuery plugin "Chosen"
(http://harvesthq.github.com/chosen/ and https://github.com/harvesthq/chosen)
in my project.
What I'm trying to achieve is update list basing on user selection (ajax call (tree based structure))
This is no bigger problem, because i can use .chosen().change(function()) and remove all unused select items and then .append new ones.
Then I can use .trigger("liszt:updated") to update list, but unfortunately all selections are deleted..
Does anyone know a way how to update chosen list without loosing selected data?
In theory I can manually remove all chosen generated elements and then populate with new ones, but then is a problem with getting SELECT "value" data.
This should be fairly simply if you save the items selected. For example:
<select data-placeholder="Choose a country..." style="width:350px;" multiple="true" class="chosen-select">
$(".chosen-select").chosen();
Now, before updating the chosen, make sure you save the items selected like this:
var chosenSelectedItems = $(".chosen-select").val(); // this gets you the select value data
// Update the select items
$('.chosen-select').trigger('liszt:updated');
$(".chosen-select").val(chosenSelectedItems);
This should be able to reset the original values before the change.
The new code now updates the list without losing the selections, and it sorts the selections based on the options order.
$('.chosen-select').trigger('chosen:updated');
Reference their project page.
This will reload the selection after xhr request (refresh list) and delete the selection if the new item list not contains the earlier selected item:
var chosenSelectedItems = $(".chosen-select").val();
$('select#GroupsStr').empty();
$.each(xhr.ReturnValue, function (index, item) {
var newOption = $('<option value="' + index + '">' + item + '</option>');
$('select#GroupsStr').append(newOption);
});
$("select#GroupsStr").val(chosenSelectedItems).trigger("chosen:updated");
I have created a few cascading or dependent dropdowns using chosen, but I have used them in addition to knockoutjs. KnockoutJS is used for binding data (in your case the select) to an object and a DOM element. Knockout also allows you to create custom bindings to handle things they may not have anticipated straight out of the box. With that being said I created a custom binding for knockout that utilized Chosen and it turned out well...
In our case we allow users to select a channel (using chosen) we then load in their locations (either by displaying or creating another select element) and trigger our custom binding which will update the data and trigger our custom binding that will tell chosen to run .trigger("liszt:updated") but keep the data in the background.
Our code is rather proprietary and I don't know that it would necessarily show you easily how to achieve this, but perhaps this will give you another way of looking at it.
Related
I have created dynamically row with drop-down list, i want to get all selected values from dropdowns of rows with JQuery. Please help me.
Since you haven't posed any code snippet, I'm just gonna wing it, assuming it's a standard <select>-box.
// Loop all parents and grab the value which is set by the browser whenever update occurs.
var values = [...document.querySelectorAll('select')].map(x =>x.value)
Having troubles getting values from dynamically added dropdown in thymeleaf.
This is my first
<select th:field="${offer.offerItemList[__${iterationStatus.index}__].mapa}" class="form-control input-sm ofa">
<option value="0" >---Choose option---</option>
<option th:each="attribute : ${offer.offerProductAttribute}" th:value="${attribute.id}" th:text="${attribute.name}"></option>
</select>
Based on selecton from this dropdown i am generating another dropdown with code similar to this :
var options = '<select th:field="offer.list" class="form-control input-sm"> <option th:value="0">--Choose--</option>';
$.each(value.offerProductAttributeValuesList, function (index, value) {
options += '<option th:value="' + value.id + '">' + value.value+ '</option>';
});
options+= '</select>';
of.closest('tr').find('td:last').html(options);
Dom elements generate fine. Everything is ok but values are never submitted with the rest of input fields.
I have done this many times but with previously rendered
<select>
dropdown on the server side, and i would just appendTo() options, but in this case i cannot do that since i potentially have more than 20 dropdowns, based on clients selection from previous dropdown.
I hope i am being clear enough about my issue.
I am gonna answer my own question, since it took me quite some time to get around this problem, and my solution will probably help someone in the future.
The problem was : i had list of objects, and each one of those objects had another list of objects.
The problem is much easier to solve if you just render entire view from the backend (i was using thymeleaf). That way you can use thymeleaf expressions to map everything correctly
Like this :
First you gonna need for each to iterate over top level list
<tr th:each="item,iterationStatus : ${offer.offerItemList}">
You need to use iterationStatus to iterate over nested List, like this :
<select th:field="${offer.offerItemList[__${iterationStatus.index}__].mapa}">
This little piece of code __${iterationStatus.index}__ will basically use iteration index and you will end up with number for each iteration and rendered view will look like this offer.offerItemList[0].mapa, and 1 and 2 and so on.
this way values will be mapped correctly, BUT, if you want to add fields dynamically things get a bit more complicated.
There is jquery issue. Since jquery pretty much binds selectors when page is rendering, even if you write add another element, say <div class="temp">
and write perfectly good jquery function something like this $('.temp').on('click',function(){ console.log("clicked")});
nothing will happen since jquery didnt bind your newly created element to any select/event listener. The solution is to use (document).
$(document).on("click",".temp",function(){console.log('clicked');})
ok we have fixed front end issue, now newly created items work, but how do i tell spring to bind them to each object within list, which is part of another list? well you will have to use iteration index again :
When rendering the view you will need to save iteration index value in each element(using hidden fields)
Get value for each input field to jquery var like this : var iteration = $(this).closest('tbody').find('td:first-child').find('input').attr('value'); ofc this is path to where i have placed hidden input field, you will have to tell jquery where to look according to your structure.
You will simulate array and index numbers like this
var options = '<select name="offerItemList['+iteration+'].mapaValues">';
And the very last thing you need to be careful about is this : Say you have Object which you would normally send from controller like this model.addAttribute("offer",offer); object Offer has attribute, list of Products, so you would access that list with simple offer.productsList, but each product has list of AttributeValues. So final setup looks like this
offer.products[0].attributes[0].name products is an arrayList of objects of class Product, attributes is an arrayList of objects of class AttributeValues and name is a String. In order to let spring create object of class AttributeValues with information spring is receiving from dynamically(and non-dinamically) created forms from the frond-end, you will need to teach him how. If your new form with has input type="text" you are sending back String, so you will need to create a Custom constructor for
your class AttributeValues which will receive a String and which will tell Spring how to "construct" instance of that class with String.
finally create two constructors, one default and one with String as a value :
public AttributeValues(){}; and another for String public AttributeValues(String n){this.name = n;};
The problem you're most likely seeing here is that you're generating thymeleaf markup on the client-side.
Thymeleaf is a server-side templating language, so the browser (and hence the Javascript) will only ever see plain HTML coming back.
Here's a few approaches to consider:
submit the form each time to get new data in, which means no javascript is required
Output every possible dropdown into your HTML, and show/hide them as needed when the user selects options. Some fairly simple Javascript required, but as you mention - the page size may be pretty big
Add a JSON endpoint to your Spring webapp (see the spring #ResponseBody annotation) that will return just the data you need, then pull that JSON data in when the user selects a dropdown using something like jQuery.get()
I have developed my application using ExtJs 4.1. I have a combobox which gets populated using Ajax call. Once the comobox is populated, I need to find an item by name and then first the select event for that item.
The problem is the way combo-box is rendered by ExtJS. I am not sure how to select an item in the right manner. CombBox is not really a <select> element but a text input with a detached drop-down list that's somewhere at the bottom of the document tree.
I do not want to hard code the id's as ExtJS randomly generate the id.
This is how the generated HTML looks
You can check the example of ExtJs combobox here
Without testing, I would suggest,
var x = require("casper").selectXPath;
casper.thenClick(".x-form-trigger.x-form-arrow-trigger")
.wait(100)
.thenClick(x("//li[contains(#class,'x-boundlist-item') and contains(text(),'Alaska')]"))
.wait(100, function(){
this.capture("screenshot.png");
});
You might also need to move the mouse into position before clicking. Use
casper.then(function(){
this.mouse.move(selector)
});
Since you have the ComboBox in a form, you could use the "name" property in the ComboBox definition and select it with:
Ext.getCmp("idOfThePanel").down('form').getForm().findField('name');
Another option, use the "reference" property. In this case I'm not sure which is the correct way to select the ComoBox:
Ext.getCmp("idOfThePanel").down('form').getForm().lookupReference('reference');
or
Ext.getCmp("idOfThePanel").lookupReference('reference');
I have a select control that I'm populating based on a list of objects:
<select data-ng-options="obj.QuestionText for obj in jumpToList track by obj.OrderNumber" data-ng-model="questionSelectionJumpTo"
data-ng-change="questionDDLChange(questionSelectionJumpTo)" id="ddlJumpTo"></select>
In my controller, I'm setting the default value when the modal that contains the drop down list appears by setting questionSelectionJumpTo like this:
$scope.questionSelectionJumpTo = $scope.jumpToList[someIndexNumber];
This works correctly.
As long as I change the value via the controller, such as when I call a function from a button, and I set $scope.questionSelectionJumpTo, it correctly updates the drop down list to show the appropriate option.
However, when I manually change the drop down list by selecting one of the options, the controller can no longer set the selected option using $scope.questionSelectionJumpTo.
Any ideas on what might be causing this? Thanks for the assist!
I have a gridview with several fields. Fields in question are PreviousPoints, GainedPoints, TotalPoints. In the edit mode PreviousPoints is not editable, just data bind, GainedPoints is a drop down list and Total Points is a Drop Down List.
When GainedPoints drop down list selected value changes, I need the TotalPoint selected value to be set to the value of PreviousPoints control + GainedPoints selected value.
But, I cannot refresh the whole page using post back.
How can it be done using JavaScript or something similar without reloading the page?
you can use the onselect() function in javascript and have your computations there.