How do I catch the user input and pass it to the create text field.
Current code shows undefined.
And the new term also not added to the list, the alert seem like not working.
$.getScript('//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.full.js',function(){
$("#mySel").select2({
width:'240px',
allowClear:true,
"language": {
"noResults": function(term) {
/* customize the no matches output */
return "Create"
}
},
escapeMarkup: function (markup) {
return markup;
}
})
.parent().find('.select2-with-searchbox').on('click','#addNew',function(){
/* add the new term */
var newTerm = $('#newTerm').val();
alert('adding:'+newTerm);
$(''+newTerm+'').appendTo('#mySel');
$('#mySel').select2('val',newTerm); // select the new term
$("#mySel").select2('close'); // close the dropdown
})
});
http://www.codeply.com/go/LxasHWd0rd
Per the select2 documentation, you can use the "tags" option to achieve what you're trying to do. Select2 already does that for you:
"If the tags option is passed into Select2, if a user types anything into the search box which doesn't already exist, it will be displayed at the top and the user will be able to select it."
Related
I have a multi-select, select2 dropdown in rails. Currently when I select some 2-3 options from the lis and when i click on backspace the selected element is getting deleted and the dropdown list with all the options are getting displayed. But when I type some initials and then select from the list and then click on backspace the dropdown list is populating the just deleted option. Is there a way where in on typing and then selecting, the dropdown list will display the full list upon clicking on backspace ??
The code that I am using is(according to https://github.com/select2/select2/issues/3354#issuecomment-132389291):
$.fn.select2.amd.require(['select2/selection/search'], function (Search) {
var oldRemoveChoice = Search.prototype.searchRemoveChoice;
Search.prototype.searchRemoveChoice = function () {
oldRemoveChoice.apply(this, arguments);
this.$search.val('');
};
$.fn.select2.amd.require(['select2/compat/matcher'], function (oldMatcher) {
$('#reports_employee_id').select2({
matcher: oldMatcher(matchStart),
templateResult: formatSearch,
templateSelection: formatSelected,
maximumSelectionLength: 25,
placeholder: " "
})
});
});
Thanks In Advance !!
Ok I understood the problem to this. I needed to handle the change.Below I am attaching the updated code for reference.
$.fn.select2.amd.require(['select2/selection/search'], function (Search) {
var oldRemoveChoice = Search.prototype.searchRemoveChoice;
Search.prototype.searchRemoveChoice = function () {
oldRemoveChoice.apply(this, arguments);
this.$search.val('');
this.handleSearch();
};
$.fn.select2.amd.require(['select2/compat/matcher'], function (oldMatcher) {
$('#reports_employee_id').select2({
matcher: oldMatcher(matchStart),
templateResult: formatSearch,
templateSelection: formatSelected,
maximumSelectionLength: 25,
placeholder: " "
})
});
});
Just needed add this line:
this.handleSearch();
and it works as expected.
I am facing issues with handling a trivial scenario during automation. I need to select a specific option using Protractor. I am passing the index of the option that I want to select, and then clicking on that to select it. However, my click() method errors out stating the click() method is undefined on that index.
Here is what I am trying to do - in my selectElements.js file, the dropdown method is defined as
const selectElement={}
selectElement.selectElementDropdown =function(element,index,milliseconds){
console.log("Selecting element by drop down","OK");
element.all(by.tagName('option')).then(function(options){
options[2].click();
//here index 2 is hardcoded, which can be changed to options[index]
});
if(typeof milliseconds!=='undefined'){
browser.sleep(milliseconds);
}
}
module.exports =selectElement;
I am using a POM structure, so the dropdown method is in a separate .js file. I am calling this in my page file
const methodDropDown = require('../BasePage/selectElements.js');
var signUpBankDetails = function(){
this.bankName = element.all(by.css('.form-group')).get(7).element(by.xpath("//label[text()='Select Bank Name']"));
//the selector is clicked to open the drop down
console.log("Start of this block =========>");
this.selectDropDownMethod = function(){
console.log("Drop Down method start ==========>");
this.bankName.click();
browser.sleep(1000);
methodDropDown.selectElementDropdown(this.bankName,0,1000);
};
I am getting the error which says -
Failed: Cannot read property 'click' of undefined
The this.bankName.click() block is working fine because, I can see that the element is clicked and the drop down appears, however the selection seems to be erroring out. I have also attached the HTML snippet of code below -
PS- The webpage is using Angular2.
When I look at the HTML I see that the label is not containing the select. The select is in the <div class="ui-helper-hidden-accessible">..</div> that is on the same level as the label.
When I look at you PO I see you are passing the label (this.bankName) as an ElementFinder with this methodDropDown.selectElementDropdown(this.bankName,0,1000);. The methodDropDown.selectElementDropdown() starts searching from the ElementFinder you pass and that is the label, not the <div class="ui-helper-hidden-accessible">..</div> that holds the select.
Maybe you can change it into something this:
// Define ElementFinder for the bankname component
const bankNameComponent = $('p-dropdown[formcontrolename="bankname"]');
// Open the dropdown
bankNameComponent.$('label').click();
// Click on an element by index
bankNameComponent.$$('select option').get(2).click();
// Or search by text in the dropdown
bankNameComponent.element(by.cssContainingText('option', 'BNI')).click();
Hope it helps
Solution 01
Select based on drop-down values attribute details
public selectOptionByValue(element: ElementArrayFinder,valueToSelect: string) : void{
let clickedIndex: number;
element.first().$$('option').filter(function(elem, index) {
return elem.getAttribute("value").then(function(value) {
if (value === valueToSelect) {
elem.click();
console.log('Yes ! Found option is:' + value);
}
return value === valueToSelect;
});
}).then(function (bool) {
}).catch(function (err) {
console.log('Ooops ! Error... '+err.message);
});
}
Solution 02
Select based on drop-down visible text details
public selectOptionByText(element: ElementArrayFinder,optionToSelect: string) : void{
let clickedIndex: number;
element.first().$$('option').filter(function(elem, index) {
return elem.getText().then(function(text) {
if (text === optionToSelect) {
elem.click();
console.log('Yes ! Found option is:' + text);
}
return text === optionToSelect;
});
}).then(function (bool) {
}).catch(function (err) {
console.log('Ooops ! Error... '+err.message);
});
}
I use autosuggestion plugin.
First I have code:
$('.auto').autocomplete({
lookup: data,
onSelect: function (suggestion) {
console.log(koji);
$('#cena_'+koji).val(suggestion.cena);
console.log(suggestion.ID);
$('#jmere'+koji).val(suggestion.jmere);
$('#kol'+koji).val(suggestion.kol);
$('#popust'+koji).val(suggestion.popust);
$('#pdv'+koji).val(suggestion.porez);
etc...
and this is OK, so when I pick some Item from list I update other input fields.
But after that I just choose other value for #cena or #jmere but if I click again on input field with class .auto (that is picked before), then onSelect is again fired and values I choose manualy #cena or #jmere been changed to suggested values.
Please help me to solve this problem. So how I can prevent call onSelect when there is already picked Item...
The JS code of onSelect is:
onSelect: function (index) {
var that = this,
onSelectCallback = that.options.onSelect,
suggestion = that.suggestions[index];
that.currentValue = that.getValue(suggestion.value);
if (that.currentValue !== that.el.val() && !that.options.preserveInput) {
that.el.val(that.currentValue);
}
that.signalHint(null);
that.suggestions = [];
that.selection = suggestion;
if ($.isFunction(onSelectCallback)) {
onSelectCallback.call(that.element, suggestion);
}
},
So is there any way to change onSelect option - to prevent calling when there is already picked some item?
You can disable the autocomplete by using disable:
$('SELECTOR').autocomplete('disable');
And you can change it back like:
$('SELECTOR').autocomplete('enable');
jsfiddle DEMO
If you want to completely remove the autocomplete you can use despose ad OP said:
$('SELECTOR').autocomplete('dispose');
With select2 dropdown, how do I get a default option to appear if no options match the user's typed input?
$("something").select2({
formatNoMatches: function(term) {
//return a search choice
}
});
I haven't been able to find anything that really matches this desired functionality within the select2 documentation or Stack Overflow.
Edit
I'm getting closer with this
$("something").select2({
formatNoMatches: function(term) {
return "<div class='select2-result-label'><span class='select2-match'></span>Other</div>"
}
});
But this is pretty hacky off the bat, and also isn't clickable.
To complement on #vararis's answer:
Select2 attached to a <select> element does not allow for custom createSearchChoice nor query functions, hence we will need to manually add an option element (I'll add it as the last option of the element so we can easily .pop it out of the results set):
<select>
...
<option value="0">Other</option>
</select>
Then pass a custom matcher function so that this "Other" option is always matched.
NOTE: Select2 3.4+ uses a different default matcher than the one currently shown in the documentation, this new one has a call to the stripDiacritics function so that a matches รก for instance. Therefore I'll apply the default matcher that comes with the Select2 version included in the page to apply its default matching algorithm to any option that's not the "Other" option:
matcher: function(term, text) {
return text==='Other' || $.fn.select2.defaults.matcher.apply(this, arguments);
},
Finally, we need to remove the "Other" option from the results set when there's any result besides the "Other" result (which is initially always in the results set):
sortResults: function(results) {
if (results.length > 1) results.pop();
return results;
}
Demo
I solved it by changing the matcher.
$('#activity_log_industry_name').select2
matcher: (term, text) ->
if text=="Other"
return true
text.toUpperCase().indexOf(term.toUpperCase())>=0
(this is in coffeescript.) The only problem is that "Other" will pop up for any search -- but this can be easily solved by modifying the sortResults function.
In version 4+ of Select2, the matcher should be passed like this:
$("something").select2({
matcher: function(params, data) {
if (data.id === "0") { // <-- option value of "Other", always appears in results
return data;
} else {
return $.fn.select2.defaults.defaults.matcher.apply(this, arguments);
}
},
});
the "Other" option should be appended to the option list like this:
<select>
...
<option value="0">Other</option>
</select>
To customize formatNoMatches use following code in your view
ui-select2="{formatNoMatches:'No Results Found'}"
Try this answer on stackoverflow
createSearchChoice: function (term) {
return { id: term, text: term };
}
Use following code to display the message as 'Other' when no matches found
$("select").select2({
formatNoMatches : function(term) {
return "Other";
}
});
try it, this work in newer version ( Select2 4.0.3 )
without add a new variable.
>>>> Fiddle here <<<<
first you need to download javascript name "github/alasql"
to search like query in data
<select id="something">
...
<option value="other">Other</option> <!-- or put this in "dataItemsList" for dynamic option -->
</select>
then in your javascript
// other than this array we will give "other" option
var ajax_search_array = ['your', 'item', 'for', 'search'];
$("#something").select2({
placeholder: "Choose your something",
//data: dataItemsList, //your dataItemsList for dynamic option
//...
//...
tags: true,
createTag: function (tag) {
// here we add %search% to search like in mysql
var name_search = "%"+tag.term.toString().toLowerCase()+"%";
// alasql search
var result = alasql('SELECT COLUMN * FROM [?] WHERE [0] LIKE ?',[ajax_search_array, name_search]);
// if no result found then show "other"
// and prevent other to appear when type "other"
if(result==false && tag.term != "other"){
return {
id: "other",
text: "Other"
};
}
});
hope this work.
Does anybody know why after clicking outside the search field and hiding autocomplete results a focus activate one more time? See please at http://layot.prestatrend.com/
Type for example just 3 letters at search field 'ipo'. Thanks for any reply!
I guess it is just the behavior of the plugin to re-focus the input if the suggestion menu was visible.
When you click outside (or use TAB to unfocus) the input, the "blur" event is triggered:
.blur(function() {
hasFocus = 0;
if (!config.mouseDownOnSelect) {
hideResults();
}
})
Executing hideResults' executes another functionhideResultsNow` which makes this check:
var wasVisible = select.visible();
...
if (wasVisible)
// position cursor at end of input field
$.Autocompleter.Selection(input, input.value.length, input.value.length);
wasVisible is true because the suggestion menu is open.
The job of $.Autocompleter.Selection is to set the text selection in the input and at the end, it focuses the input:
$.Autocompleter.Selection = function(field, start, end) {
if (field.createTextRange) {
...
} else if (field.setSelectionRange) {
...
} else {
...
}
field.focus();
};
If you click again outside the input, the variable wasVisible is false, because the suggestion menu is not open anymore, and the $.Autocompleter.Selection is not executed so the input is not re-focused.
The only way I found: Destroy the autocomplete on focus event for re initializing it.
function defaultFocusAction(e, options) {
if($(e.currentTarget).val() == '') {
$(e.currentTarget).autocomplete('destroy');
$(e.currentTarget).autocomplete(options);
}
$(e.currentTarget).trigger('keydown.autocomplete');
}
var options = {
autoFocus : false,
delay : 0,
minLength: 0,
source: ['foo', 'bar']
};
$('input.autocomplete').autocomplete(options).focus(function(e) {
defaultFocusAction(e, options);
});