often I find myself suprized about simple things, I'm not sure but I believe that this might be one of them.
Often I find myself needing to merge get attributes, especially within filters and search pages within sites. This come be at times quite complicated, as you might want to remove and add parameters dynamically.
Simple way to do it is to use a form, but this get complicated, when adding elements that don't belong within a form. e.g. pagination
For example I might have a URL such as the following
http://www.example.org/ninja_search/?speed__gt=5&night_sight=1&page=1
How would I merge such URL with page=2, substituting the 1 with the new value? Is javascript the only option?
?speed__gt=5&night_sight=1&page=1 + page=2 = ?speed__gt=5&night_sight=1&page=2
Thanks :)
The solution is to use [] to explicitly create an array from the parameters, providing your server side language supports it:
?speed__gt=5&night_sight=1&page[]=1&page[]=2
For example, if your server-side language is PHP, $_GET['page'] will now return an array with 1 as the first element and 2 as the second.
You can use this technique in forms too, by applying it to the name attribute:
<form id="myform">
<input type="hidden" name="page[]" value="1" />
<input type="hidden" name="page[]" value="2" />
</form>
If you're talking about adding a second parameter and ignoring the first, this will happen anyway - the second provided parameter will override the first. Assuming
?speed__gt=5&night_sight=1&page=1&page=2
The value of page at the server will be 2, because the last value given takes priority.
Related
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()
Is it possible to append some HTML to the end of a typeahead? I've tried many different things but none have worked.
What I'm trying to do is have the last result of the typeahead be Search for "< what the user typed into the input >".
Here's what I've tried on JSFiddle: http://jsfiddle.net/MgcDU/8621/
What I expected it to do was append the <li> at the end of the dropdown once it's created, but it doesn't. Why?
HTML:
<input type="text" data-source="["Alabama","Alaska","Arizona","Arkansas","California","Colorado","Connecticut","Delaware","Florida","Georgia","Hawaii","Idaho","Illinois","Indiana","Iowa","Kansas","Kentucky","Louisiana","Maine","Maryland","Massachusetts","Michigan","Minnesota","Mississippi","Missouri","Montana","Nebraska","Nevada","New Hampshire","New Jersey","New Mexico","New York","North Dakota","North Carolina","Ohio","Oklahoma","Oregon","Pennsylvania","Rhode Island","South Carolina","South Dakota","Tennessee","Texas","Utah","Vermont","Virginia","Washington","West Virginia","Wisconsin","Wyoming"]" data-items="10" data-provide="typeahead" style="margin: 0 auto;" class="span3">
jQuery:
$(".typeahead.dropdown-menu").append('<li data-value="Custom" class="">CUSTOM TEXT</li>');
The dropdown menu is built during the typeahead filtering process. If you inspect it "on load", you will notice it is empty.
Depending on your specific problem you're trying to solve, i can think of two possible solutions.
One solution would be to extend the typeahead plugin and provide a custom "render" function. This would allow you to modify the list rendering process and append additional <li>s as well as anything else you like. This is probably regarded as the "best way".
Another more hacky solution would be to place your custom value in the data source, then provide a custom "matcher" function which runs the original matcher along with an additional clause for your custom value.
Of course solutions are tied to problems and without really knowing the very specifics of what you want to do, i can't recommend which one to use. But those are your two options as far as i can think.
A client is asking that a textfield containing phone-number data be split into two -- one for country code, the other for the rest of the number.
Alas, this field is pretty hard-coded into the system and all data collected thus far has been as one consolidated field (and thus saved as one column in the database).
I'm thus thinking the best answer might be to do the following:
Using Javascript, replace the single text field with two text fields.
These then become merged back into the original text field when the user clicks the submit button.
Bonus marks if there's a way to separate that field back into two again when it's read from the database (I.e., when an administrator views the entry). Note that the data format must be consistent -- I don't want to mix the existing string data with, say, a bunch of JSON strings.
Is this the best way to go about this? Are there any foreseeable problems (beyond the user not having JavaScript enabled) with this approach? Is there a jQuery plugin that's designed to do stuff like this?
I also need to validate it as a valid phone number at some point, but I can figure that out myself.
Rather than splitting the text field into two, you may use the masked input JQuery plug-in
http://digitalbush.com/projects/masked-input-plugin/
$(document).ready(function(){
$("#phone").mask("(999)999999");
});
Sample JS : http://jsfiddle.net/vGeMV/3/
Edit:
For point 3 : If you want to really split the number into two and display it, you may split it from the right (usually 7 digits) rather than left so that even if country code is present or not, you will get the correct split.
If you dont want to use a plugin you can always check out this snippet I made on jsFiddle
If you want to make sure it works in the JS just change the display:'none' to display:'block'
here is my JavaScript
$(function() {
$('#phone').css({ display:'none' });
$('#phone').after(') <input type="text" name="phoneMainNumber" id="phoneMainNumber" />').after('(<input type="text" value="555" name="phoneAreaCode" id="phoneAreaCode" style="width:30px;" />');
bindChange();
});
function bindChange() {
$('#phone').val('('+$('#phoneAreaCode').val()+') ');
$('#phoneMainNumber, #phoneAreaCode').keyup(function() {
$('#phone').val('('+$('#phoneAreaCode').val()+') '+$('#phoneMainNumber').val());
});
}
is it possible to get the value of the hidden field that is defined in the gridview to the javascript function so I have a gridview that has a linked button defined in it. If the user clicks on the link button, I am invoking a javascript function. I want the hidden field values in the javascript function.
also, I was wondering if it is possible to pass multiple values in one hiden field and then split them later in the javascript function.
any help will be appreciated. I don't want to go to code behind and then invoke the javascript function from there.
The first task is to determine a "suitable selector" for the hidden fields - this can be the ID (get via control.ClientID) of each individual hidden field or a more general selector like "all hidden fields in a particular div (with a particular ID)". Use <%= .. %> (or <%# .. %> in a data-binding context) to put this information into the actual HTML response.
The exact approach will vary - basically, whichever is easiest - for the task.
Then, using your favorite library or advanced browser with applicable selector support (it is easier to find good libraries)1, use the given selector. In jQuery, this might be similar to the following, where fn is the function to process all the values. The actual selector is the stuff in quotes:
fn(jQuery("#clientIdOfGridView input[type='hidden']"))
Which might be written in ASP.NET, which is how the appropriate element ID is injected:
fn(jQuery("#<%= gridView.ClientID %> input[type='hidden']"))
These will both pass a jQuery object representing the hidden field elements to the function. Then use val() and/or each() (see the jQuery documentation and other SO questions) for usage.
There are many questions relating to just jQuery and "selecting values", so this is entire "answer" is really to provide a lead on how to get started - Happy coding :)
1 While this can be done manually with "old-school" finding a element by ID and DOM traversal, I find it a waste of my time to do such a task manually. I like jQuery but there are alternatives. Use the existing wheels; they roll relatively fast.
you can specify as much values in one value-attribute of a hidden field as you like. You must make sure use a delimiter like "," or "#" which you can use in your function to split the string of values according to your needs.
I have an iterator in jsp and the iterator contains 2 lists:
<s:iterator value="reportNamesList">
<s:select name="hour" listKey="codeDesc" listValue="code" list="hourList" />
<s:select name="minute" listKey="codeDesc" listValue="code" list="minutesList" />
</s:iterator>
Now my requirement is that when hour value is selected (say as 10), the minute dropdown value should also become 10.
I am using javascript. Kindly suggest how to do it.
#Naved is correct; you interact with tag-produced DOM elements the same way as any other (although I'd use jQuery and save yourself a lot of time). You can explicitly set an id by using the id element.
In your case, since you'll have multiple groups of select boxes, you'll need to create the id based on something unique in the reportNamesList, perhaps an id. Your id attribute, then, would probably look something like id="hours_%{id} or if you use the <s:iterator>'s var attribute, id=hours_%{#foo.id}.
Your JavaScript would need to bind each hours select to its associated minutes select.
The code seems that you are coding it in Struts2. Although I am not very much aware of it but the simplest way I found to write any javascript for these types of framework is
Run your code in browser and view the page source
Locate the id or name given to your desired control (in your case it is select for hour). Say it selHour.
Write the javascript code using getElementById('selHour') or getElementsByName('selHour') and do your stuff.
I hope this will help you to give the proper output.