dojo.data.ItemFileReadStore: Invalid item argument with Dijit combobox - javascript

I have a jsp page with a dijit.form.ComboBox which is populated by a dojo.data.ItemFileReadStore connecting to a back end java server. It works almost as expected, the combobox shows the results correectly. Problem is that I receive a 'dojo.data.ItemFileReadStore: Invalid item argument.' when scrolling in a results list with the keyboard arrow keys. Selecting with the mouse however works fine.
Dojo version is 1.2.3
This is how I've put it in place on my jsp:
<input type="text" id="value"
dojoType="dijit.form.ComboBox"
autoComplete="false"
searchAttr="name"
forceValidOption="true"
hasDownArrow="false"
onKeyUp="populateValue"
/>
<script type="text/javascript">
function populateValue() {
valueWidget = dijit.byId("value");
var selectedValue = valueWidget.getValue();
var url = "${contextPath}/someUrl?selectedValue=" + selectedValue + "%";
store = new dojo.data.ItemFileReadStore({url:url});
valueWidget.store = store;
return;
}
</script>
Here is the JSON I receive from the server:
{"items":[
{"name":"My string 1","label":"My string 1"},
{"name":"My string 2","label":"My string 2"},
{"name":"Mev.","label":"Mev."}],
"identifier":"name"}
Any idea what's going wrong here?

Solved it. Problem seemed to be the onKeyUp event on the combobox. When I changed this to onKeyPress, arrowing down the list gives no more errors.
Compared to onKeyUp, onKeyPress gives me in fact a delay of one character because the event is triggered when the character is not actually typed already. Any idea how I could overcome this?

Related

Dynamic loaded datalist options with AJAX in Firefox

For different reasons I want to get rid of Jquery UI autocomplete function and replace it by HTML5 datalists with dynamic loaded options field. I searched on this topic quite a few days and found also different answers on stackoverflow, like How do you refresh an HTML5 datalist using JavaScript? which I think is pretty close to what I search for.
I want the datalist for choosing tags, which will be written comma separated in the input field. The problem is that the datalist is only shown correctly for the first tag. The suggestion for the second one is not shown during typing "letters".
Now to the Process:
Typing: app
Server Response:
['apple','pinapple','snapper']
Shown datalist suggestion:
apple
pinapple
snapper
I now choose: apple, which is written to the input field, and afterwards:
Typing: ,in
Server Response:
['intest','instructor','insula']
Shown datalist suggestion: nothing, and this is the problem
BUT:
If I now hit backspace and delete the last sign, in the input field now stands:
apple, i
Then Firefox shows as options:
apple, intest
apple, instructor
apple, insula
I know that there is a comparison with the value or innerHTML Field, so that I use:
<option value="apple, intest">apple, intest</option>
Now the code example:
HTML
<input list="autocompleteList" type="text" class="form-control" name="Tags" id="Tags">
<datalist id="autocompleteList"></datalist>
JS
// Used for querying only the last word of input field
function extractLast( term ) { return split( term ).pop(); }
$( document ).on( "input","*[name=Tags]", function( e ) {
var _this = $(this);
var input = _this.val();
var first_part;
// If a first tag is already inserted, now extract it for later use
if ( input.split(/,|,\s*| /).length > 1 ) {
var temp = input.split(/,|,\s*| /);
first_part = temp.filter(function (el) { return el.trim() != ""; }).slice(0,-1).join(', ') + ', ';
console.log("EXTRACTED FIRST PART " + first_part);
} else {
first_part = '';
}
if ( extractLast(input).length >= 2 ) {
$.ajax({
dataType: "json",
type : 'POST',
async:true,
url: 'example.com/suggester',
data: {term: extractLast( input )},
success: function (data) {
$("#autocompleteList").empty();
for (i=0; i<data.length; i++) {
$("#autocompleteList").append('<option value="' + first_part + data[i] + '">' + first_part + data[i] + '</option>');
}
// Array of Tags
console.log("DATA FROM SERVER: " + data);
// For inspection
console.log("CONTENT OF AUTOCOMPLETE LIST: " + $('#autocompleteList').html());
}
});
}
});
What I already have tested:
Changing: from input to keypress, keyup, keydown, change -> no success
Manually trigger events: _this.focus() or other --> no response
Using JQuery show() on the datalist
Embed the options into HTML-select. In this situation the datalist is also not working as expected, but the dropdown menu triggered by the select works fine and refreshes quickly.
So, finally:
How can I achieve, that the datalist options opens when typing letters without hitting backspace?
Thank you in advance!
I stumbled upon this post which exactly describes the issue I was facing and was surprised to see no answers.
The autocomplete attribute needs to be set. In your case
<input autoComplete="off" list="autocompleteList" type="text" class="form-control" name="Tags" id="Tags">
Note the capital C in the attribute.
According to this post, the problem was in React which uses camel-cased attributes. I'm not using React, but it worked for me nevertheless.
I also had the issue of having to populate an HTML Datalist with Ajax via jQuery, and the elements would not show up without hitting backspace on Firefox, despite working on Edge and Chrome. The workaround posted by Shrestha Ghosh did not work for me, neither did another workaround posted here, which suggested setting the autocomplete="off" then immediately back to autocomplete="on" with JavaScript/jQuery (i.e. with Element.SetAttribute() or jQuery.attr() respectively).
Instead, I noticed that the datalist would show up if I unfocused and refocused (i.e. clicked off then clicked in) the HTML input element. So, if anybody for which this issue is still relevant can use jQuery, it might be worth trying jQuery.Blur() and jQuery.Focus() too; this is a solution I haven't seen posted yet (tested on Firefox 80.0 64-bit).
That is:
$("#your-input-element").keypress(function(){
$(this).blur();
$(this).focus();
}
Note keypress instead of keydown; this avoids triggering the blur and focus when trying to navigate down the list with the down-arrow key. It's not a fantastically elegant solution, but for my use case it works quite well.
I had similar issue on Firefox where the drop down is not showing even if the result came back (JS HttpRequest) and I can see it at the DOM.
the solution for me was to add empty (as shown below) and replace it with the new data which came after sending the request.
<div class="form-group-input">
<label for="client_name" class="hidden-label">Client Name</label>
<input list="clients_list" autoComplete="off" type="text" name="client_name" id="client_name" placeholder="Client Name" >
<datalist id="clients_list"><option value=""></datalist>
</div><!-- form group input -->
Thanks

ng-model fails to bind the values entered with a touch event

I'm using a JQuery + Bootstrap keyboard that is configured specifically only for touch inputs in my Angular app (If i use the mouse to click on the keys, keyboard will close without typing any. It is written to close on on click events).
Mobile-first-Virtual-Keyboard-Plugin-With-jQuery-Bootstrap
My problem is when i enter something to an input box whcih is binded to my controller using ng-model like the following code,
<input autocomplete="false" class="textInputSeeThrough keyboard"
ng-model="patientNIC" type="text" id="nic"
name="patientNICTxtbox" autofocus
placeholder="--- ENTER NIC NUMBER ---">
it does not get binded properly. But if i use plain javascript to traverse the DOM and get the element value in my controller instead of using $scope to get the value, i can get the value properly.
var val1 = $scope.patientNIC; // this doesn't work
var val2 = document.getElementById("nic"); // this works
alert(val1);
alert(val2.value);
So it is clearly not something wrong with the Keyboard. Does angular js have any known problems working with touch events? I couldn't find any. Can someone explain me why this is happening? Thanks in advace.
Simple answer is: Angular doesn't know about changing in input. Every change must be wrap in $apply or $timeout.
Look at this
Update Angular model after setting input value with jQuery
No Need to worry about, set values to input element using jquery / Javascript .
Please paste the following script in your html block / js (jquery)
!function (n, t) { "use strict"; var r = n.fn.val; n.fn.val = function (n) { if (!arguments.length) return r.call(this); var e = r.call(this, n); return t.element(this[0]).triggerHandler("input"), e } }(window.jQuery, window.angular);
Even we don't need to reassign values to ng object / trigger the input individually.
cheers !

How to set the value of a text input with MooTools

I have just begun playing with MooTools, and I don't understand why the following happens:
var input = new Element('input');
input.set('type','text');
input.set('value','this is the value');
console.log(input);
results in: <input type=​"text">​, so setting the value hasn't worked.
But if I do this:
var input = new Element('input');
input.set('type','text');
input.set('someValue','this is the value');
console.log(input);
I get the expected result of <input type=​"text" somevalue=​"this is the value">​.
Am I overlooking something, is what I am trying to do not allowed, is this a bug in Chrome (11.0.696.71, OS X) or am I doing something else wrong?
Update: thanks for your answer! You are right, the value is actually being set; console.log(input.get('value')) gives back the proper value and I can see the value in the input field when I append the input object to the DOM.
Apparently, the value setting is just not reflected as an attribute of the HTML element, but only stored internally.
Are you sure the value isn't being set?
What do you get when you call: input.get('value')
I tested this (in firefox) and even though the console just logs <input type=​"text"> the value does in fact get set. Try adding the element to the page and you'll see it :)
I've had a similar problem with this 'red herring' which I've since solved, and thought I'd share.
I'm trying to make certain cells of a table row editable when the user clicks on the row:
var cells = this.getElements("td");
for (var ix=0;ix<cells.length; ix++){
if (cells[ix].hasClass("edType_text")){
var celltext = cells[ix].get("text");
cells[ix].set('text','');
var editTag = new Element ('input',{type:'text','value':celltext});
editTag.inject(cells[ix]);
}
}
This seemed to work OK but when I clicked on the cell I couldn't edit it. Firebug and Chrome tools showed the added input tag as
<input type='text'>
instead of the expected:
<input type='text' value='xxxxxx' />
However this is perfectly normal as commented on above.
Spotted the 'deliberate' error ?
Of course when I clicked on the input field it triggered the mouse event on the row again, thus preventing me getting at the input!!!! :-{
To avoid this just add this line of code at the end of the if block:
editTag.addEvent("mousedown",function(event){event.stopPropagation();});

Clear default values using onsubmit

I need to clear the default values from input fields using js, but all of my attempts so far have failed to target and clear the fields. I was hoping to use onSubmit to excute a function to clear all default values (if the user has not changed them) before the form is submitted.
<form method='get' class='custom_search widget custom_search_custom_fields__search' onSubmit='clearDefaults' action='http://www.example.com' >
<input name='cs-Price-2' id='cs-Price-2' class='short_form' value='Min. Price' />
<input name='cs-Price-3' id='cs-Price-3' class='short_form' value='Max Price' />
<input type='submit' name='search' class='formbutton' value=''/>
</form>
How would you accomplish this?
Read the ids+values of all your fields when the page first loads (using something like jquery to get all "textarea", "input" and "select" tags for example)
On submit, compare the now contained values to what you stored on loading the page
Replace the ones that have not changed with empty values
If it's still unclear, describe where you're getting stuck and I'll describe more in depth.
Edit: Adding some code, using jQuery. It's only for the textarea-tag and it doesn't respond to the actual events, but hopefully it explains the idea further:
// Keep default values here
var defaults = {};
// Run something like this on load
$('textarea').each(function(i, e) {
defaults[$(e).attr('id')] = $(e).text();
});
// Run something like this before submit
$('textarea').each(function(i, e){
if (defaults[$(e).attr('id')] === $(e).text())
$(e).text('');
})
Edit: Adding some more code for more detailed help. This should be somewhat complete code (with a quality disclaimer since I'm by no means a jQuery expert) and just requires to be included on your page. Nothing else has to be done, except giving all your input tags unique ids and type="text" (but they should have that anyway):
$(document).ready(function(){
// Default values will live here
var defaults = {};
// This reads and stores all text input defaults for later use
$('input[type=text]').each(function(){
defaults[$(this).attr('id')] = $(this).text();
});
// For each of your submit buttons,
// add an event handler for the submit event
// that finds all text inputs and clears the ones not changed
$('input[type=submit]').each(function(){
$(this).submit(function(){
$('input[type=text]').each(function(){
if (defaults[$(this).attr('id')] === $(this).text())
$(this).text('');
});
});
});
});
If this still doesn't make any sense, you should read some tutorials about jQuery and/or javascript.
Note: This is currently only supported in Google Chrome and Safari. I do not expect this to be a satisfactory answer to your problem, but I think it should be noted how this problem can be tackled in HTML 5.
HTML 5 introduced the placeholder attribute, which does not get submitted unless it was replaced:
<form>
<input name="q" placeholder="Search Bookmarks and History">
<input type="submit" value="Search">
</form>
Further reading:
DiveintoHTML5.ep.io: Live Example... And checking if the placeholder tag is supported
DiveintoHTML5.ep.io: Placeholder text
1) Instead of checking for changes on the client side you can check for the changes on the client side.
In the Page_Init function you will have values stored in the viewstate & the values in the text fields or whichever controls you are using.
You can compare the values and if they are not equal then set the Text to blank.
2) May I ask, what functionality are you trying to achieve ?
U can achieve it by using this in your submit function
function clearDefaults()
{
if(document.getElementById('cs-Price-2').value=="Min. Price")
{
document.getElementById('cs-Price-2').value='';
}
}

How can I use the jQuery Autocomplete plugin for linked input fields?

I'm using the jQuery Autocomplete plugin. I have two input fields on a form, inputfield1 and inputfield2.
I attached autocomplete to the first field. When the that field loses focus, I want to check if a value was entered and if so, then make an AJAX call to retrieve some "\n"-separated strings and use them to drive autocomplete on the second field.
Below is the code I'm using to do that:
/*Receive data from server for autocomplete*/
$("#inputfield1").autocomplete("<url1>");
$("#inputfield1").blur(function(){
// Attach autocomplete if inputfield1 field is not empty
if($("#inputfield1").val() != ""){
var url = "<url2>?q="+$("#inputfield1").val();
$.get(url,function(data){
result=data.split("\n");
$("#inputfield2").autocomplete(result);
});
}
});
But a strange thing is happening: I am able to attach autocomplete to the first field successfully, but I have to give focus twice to the second field in order to use autocomplete on it. Is there any way to fix this problem?
Try this simplified test. If this works check if your result really contains what you think (alert it or write it to console). There could be other characters after splitting (namely whitespace (leading spaces, \t or \r) try trimming every value of the result array.
var data1 = ["a123", "b123", "c123", "d123", "e123", "f123", "g123", "h123", "i123", "j123", "k123", "l123", "m123", "n123", "o123", "p123", "q123", "r123", "s123", "t123", "u123", "v123", "w123", "x123", "y123", "z123"];
var data2 = 'a123\nb123\nc123\nd123\ne123\nf123\ng123\nh123\ni123\nj123\nk123\nl123\nm123\nn123\no123\np123\nq123\nr123\ns123\nt123\nu123\nv123\nw123\nx123\ny123\nz123';
$("#inputfield1").autocomplete(data1);
$("#inputfield1").blur(function(){
if($("#inputfield1").val() != ""){
var result=data2.split("\n");
$("#inputfield2").autocomplete(result);
}
});
I found this code in the current version of the autocomplete plugin:
.click(function(event) {
$(target(event)).addClass(CLASSES.ACTIVE);
select();
// TODO provide option to avoid setting focus again after selection? useful for cleanup-on-focus
input.focus();
return false;
It seems to put focus back on itself after a click. This might be messing you up.
Instead of handling the blur() event, maybe you'll have better luck if you handle the autocomplete plugin's result() event.
/*Receive data from server for autocomplete*/
$("#inputfield1").autocomplete("<url1>");
$("#inputfield1").result(function(event, data, formatted){
// Attach autocomplete if inputfield1 field is not empty
if(data){
var url = "<url2>?q="+data;
$.get(url,function(data1){
result=data1.split("\n");
$("#inputfield2").autocomplete(result);
});
}
});
Make sure you're using the latest version of the Autocomplete plugin. There was a bug in versions prior to 1.1 where if you enabled autocomplete on a field after that field had focus (as would happen in your example if you tabbed from the first input field directly into the second) it wouldn't work properly until focus was lost and then restored again...
Here's a quick demo that shows this construct working with the latest Autocomplete version.
You say you need to select #inputfield2 twice so the autocomplete event binds to it, right?
I'm just thinking.. can it be possible that you are using your tab key on your keyboard to select #inputfield2 and when that doesn't work you select #inputfield2 with your mouse? If so, isn't it possible that the #inputfield1 blur event doesn't kick in until you "unselect" it with your mouse (maybe some kind of bug)?
I haven't tried this, it's just a thought.

Categories