set default selected value in selectize input - javascript

I have a form , where I want some default selected value when the page loaded. Something like this:
Here is my current code which I am using for getting options from remote server:
(function () { // function for selectize
axios.get('/api/tags/', {
headers: {'Authorization': "JWT " + sessionStorage.getItem('token')}
}).then(function (response) {
let nisha = [];
response.data.map(function (hiren) {
let bunny = {'value': '', 'text': ''};
bunny['value'] = hiren.name;
bunny['text'] = hiren.name;
nisha.push(bunny);
});
let $select = $('#tags').selectize({
delimiter: ';',
persist: false,
options: nisha,
items: tags,
create: function(input) {
return {
value: input,
text: input
}
}
})
//var selectize = $select[0].selectize;
//selectize.setValue('something', true);
}).catch(function (error) {
console.error(error);
})
})();

You can pass default values in value attribute comma separated like below :
<input type="text" id="tags" class="demo-default selectized" value="awesome,neat" tabindex="-1" style="display: none;">
And if not working, try creating jsfiddle for this snippet.
Hope this will work.

Related

Select2: Update option after selecting new tag

I implemented a tagging system where you can choose from existing tags or add new tags. After a new tag has been selected it will persisted using an AJAX call.
For achieving this I use the callback createTag and the event select2:select. Because I like to create the tag only when it is selected I do an AJAX call for this if the event select2:select gets triggered.
The problem is that I need to update the already created option of select2 with the ID I get from persisting my new tag to the database. What's the cleanest solution for this?
Here's what I have:
$('select.tags').select2({
tags: true,
ajax: {
url: '{{ path('tag_auto_complete') }}',
processResults: function (data) {
return {
results: data.items,
pagination: {
more: false
}
};
}
},
createTag: function (tag) {
return {
id: tag.term, // <-- this one should get exchanged after persisting the new tag
text: tag.term,
tag: true
};
}
}).on('select2:select', function (evt) {
if(evt.params.data.tag == false) {
return;
}
$.post('{{ path('tag_crrate_auto_complete') }}', { name: evt.params.data.text }, function( data ) {
// ----> Here I need to update the option created in "createTag" with the ID
option_to_update.value = data.id;
}, "json");
});
My problem was that I did not add the new tag as an <option> tag to the native select field.
This is necessary because select2 checks for the values set trough select2.val(values) if an <option> tag with this value does exist. If not select2 silently throws the value out of the array and sets the array of values which have a corresponding option tag in the underlying select field.
So this is how it works correct now (for select2 4.0.x):
$('select.tags').select2({
tags: true,
ajax: {
url: '{{ path('tag_auto_complete') }}',
processResults: function (data) {
return {
results: data.items,
pagination: {
more: false
}
};
}
},
createTag: function (tag) {
return {
id: tag.term,
text: tag.term,
tag: true
};
}
}).on('select2:select', function (evt) {
if(evt.params.data.tag == false) {
return;
}
var select2Element = $(this);
$.post('{{ path('tag_crrate_auto_complete') }}', { name: evt.params.data.text }, function( data ) {
// Add HTML option to select field
$('<option value="' + data.id + '">' + data.text + '</option>').appendTo(select2Element);
// Replace the tag name in the current selection with the new persisted ID
var selection = select2Element.val();
var index = selection.indexOf(data.text);
if (index !== -1) {
selection[index] = data.id.toString();
}
select2Element.val(selection).trigger('change');
}, 'json');
});
The minimal AJAX response (JSON format) has to look like this:
[
{'id': '1', 'text': 'foo'},
{'id': '2', 'text': 'bar'},
{'id': '3', 'text': 'baz'}
]
You may add additional data to each result for let's say own rendering of the result list with additional data in it.
Just to update:
The new syntax is
e.params.args.data.id
not
e.params.data.id

Select2 inserts an empty text option in the dynamic list

I am using Select2 with Jquery-editable and encountering an abnormal behavior of Select2, what I am doing is displaying editable table of information using ejs template, and as user clicks on CBA opens up a select2 box which have the originally selected result, and then user can add or delete options in it, options comes from Database source, and when user selects an options it adds an empty option in database with the selected option , the array looks like this
[ "ABCD", "ONAB", "" , "BCNU" ]
I read somewhere about allowClear: true and add a placeHolder but It doesn't helped me at all. As everything is done dynamically I can't find where that empty option is added.
Code is below:
Ejs/HTML code for Select 2
<tr>
<td width="40%">Select CBA(s)</td>
<td>
<a class="cbaSelectUnit" data-emptytext="Select CBA(s)" data-original-title="Select CBA(s)" data-type="select2"></a>
</td>
Javascript for Select 2
$("a[data-name='Cba']").editable({
showbuttons: 'false',
emptytext: 'None',
display: function(values) {
var html = [];
html.push(values);
$(this).html(html);
},
select2: {
multiple: true,
allowClear: true,
placeholder: "Select CBA(s)",
ajax: {
// url is copied from data-source via x-editable option-passing mechanism
dataType: 'json',
// pass the '?format=select2' parameter to API call for the select2-specific format
data: function(term, page) {
return {
deptId: departmentId,
format: 'select2'
};
},
// transform returned results into the format used by select2
results: function(data, page) {
return {
results: data
};
}
},
// what is shown in the list
formatResult: function(cba) {
return cba.text;
},
// what will appear in the selected tag box
formatSelection: function(cba) {
return cba.text;
},
// rendering id of the values to data.value requirement for Select 2
id: function(cba) {
return cba.value;
},
// what is shown in the selected-tags box
initSelection: function(element, callback) {
var id = $(element).val(),
result = id.replace(/^,\s*$/, ',').split(",").map(function(v) {
return {
id: v,
text: v
};
});
callback(result);
}
}
});
Format in which Code is returned from the database:-
Facility.findOne({ _id: department.Facility }, function(err, facility) {
if (err) {
res.send(500, err);
} else if (!facility) {
res.send(404, 'Facility not found');
} else if (req.query.format && req.query.format === 'select2') {
var result = facility.Cba.map(function(c) {
return { value: c, text: c };
});
res.json(result);
}
});
Image showing an empty box added by itself
How Array looks after I edit
So it was just a simple syntax error, I was doing found out by myself,
I was returning cba.value as id, but the initSelection was returning
{id: v, text: v}
it should be value & text instead of id & text.
// what is shown in the selected-tags box
initSelection: function(element, callback) {
var id = $(element).val(),
result = id.replace(/^,\s*$/, ',').split(",").map(function(v) {
return {
value: v,
text: v
};
});
callback(result);
}

Select2 - avoiding duplicates tags

How can I avoiding duplicates tags in Select2 input?
When I type tag name on the keyboard string is added to input field, but when I select tag from dropdown list (results from the database) the id is added to input (look at console.log on screenshot). So I can select tag from list and add the same tag from keyboard.
Moreover, I need the text of tags, not id from dropdown list while submit a form.
Full resolution
HTML:
<input type="hidden" id="categories" name="categories" style="width:100%" value="${categories}">
JS:
$("#categories").select2({
tags: true,
tokenSeparators: [","],
placeholder: "Dodaj",
multiple: false,
minimumInputLength: 3,
maximumInputLength: 50,
maximumSelectionSize: 20,
ajax: {
quietMillis: 150,
url: '${request.route_url("select2")}',
dataType: 'json',
data: function (term, page) {
return {
q: term,
page_limit: 10,
page: page,
};
},
results: function (data, page) {
var more = (page * 10) < data.total;
return {results: data.categories, more: more};
}
},
initSelection: function (element, callback) {
var data = [];
$(element.val().split(",")).each(function () {
data.push({id: this, text: this});
});
callback(data);
},
createSearchChoice: function (term) {
return { id: term, text: term };
},
}).change(function (e) {
if (e.added) {
console.log($("#categories").val())
console.log(e)
}
});
Have same problem, but I figured it out to find a way around.
I'm getting text and ids, but on the server side I'm creating from given id new objects, which are well read.
$tagsArray = explode(',', $tagNames); // it contains of my input select2 value (with ids)
foreach ($tagsArray as $tag)
{
if (is_numeric($tag))
{
$tags->append(TagQuery::create()->filterById($tag)->findOneOrCreate());
}
elseif (!empty($tag))
{
$tags->append(TagQuery::create()->filterByName($tag)->findOneOrCreate());
}
}
Hope it helps.
at first use select 2
and then do this:
$("select").change(function() { var tr = $(this).closest("tr");
tr.find("select option").attr("disabled",""); //enable everything
//collect the values from selected;
var arr = $.map
(
tr.find("select option:selected"), function(n)
{
return n.value;
}
);
//disable elements
tr.find("select option").filter(function()
{
return $.inArray($(this).val(),arr)>-1; //if value is in the array of selected values
}).attr("disabled","disabled"); });

knockoutjs bindings issue

I'm having issues with my knockoutjs implementation. Seems to be working fine on Chrome and Safari IE and FF have thrown a hissy fit.
The message which I encounter is as follows:
Unable to parse bindings. Message: TypeError: 'AccountName' is
undefined; Bindings value: value: AccountName
The issue is happening within a script tag which serves as a knockout template:
<div id="newAccountDialog" class="dialog" data-bind="dialog: { autoOpen: false, resizable: false, modal: true, width: 350, title: 'Exchange Account'}, template: { name: 'dialogFormTemplate', data: CurrentAccount }, openDialog: IsNew"></div>
<script id="dialogFormTemplate" type="text/html">
<form id="dialogForm">
<h1>Exchange Account Manager</h1>
<p>Add new or edit an existing exchange account settings.</p>
<label for="AccountName">
Account
</label>
<input id="AccountName" name="AccountName" type="text" data-bind="value: AccountName, valueUpdate: 'afterkeydown'" class="ui-widget-content ui-corner-all" />
<div class="buttonsContainer floatRight">
<button id="Save" data-bind="click: $root.SaveAccount, dialogcmd: { id: 'newAccountDialog', cmd: 'close'}, jqButton: { icons: { primary: 'ui-icon-disk' } }">Save & Close</button>
</div>
</form>
</script>
I assume some sort of early binding is being triggered on the template
data : CurrentAccount
where an undefined / null is being passed into CurrentAccount. I have seen this issue outside of script tags, but only if the observable is not defined or null.
My viewmodel looks as following:
var AccountModel = function () {
var self = this;
self.Accounts = ko.observableArray([]);
self.CurrentAccount = ko.observable(null);
self.IsNew = ko.observable(false);
self.LoadAccounts = function () {
$account.invoke("GetAccounts", {}, function (data) {
var mapped = $.map(data, function (item) {
var account = new Account(item);
var innerMapped = $.map(item.Mailboxes, function (mailbox) {
return new Mailbox(mailbox);
});
account.Mailboxes(innerMapped);
return account;
});
self.Accounts(mapped);
});
}
self.EditAccount = function (data) {
self.CurrentAccount(data);
self.IsNew(true);
}
self.SaveAccount = function () {
if (self.CurrentAccount().Id() <= 0) {
$account.invoke('AddAccount', ko.toJS(self.CurrentAccount()), function (data) {
self.Accounts.push(new Account(data));
self.CurrentAccount(new Account(data));
self.IsNew(true);
});
} else {
$account.invoke('UpdateAccount', ko.toJS(self.CurrentAccount()), function (data) {
//self.CurrentAccount(new Account(data));
});
}
}
self.CreateAccount = function () {
self.IsNew(true);
var account = { Id: 0, AccountName: '', IsNTLM: -1, Email: '', Password: '', Domain: 'mydomain', ExchangeVersion: 1, Mailboxes: [] };
self.CurrentAccount(new Account(account));
}
};
My dialog bindingHandler is defined as follows:
ko.bindingHandlers.dialog = {
init: function (element, valueAccessor) {
var options = ko.utils.unwrapObservable(valueAccessor()) || {};
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).dialog('destroy');
});
$(element).dialog(options);
}
};
I have ommited the Account object, as it is possibly not required in this context.
I would appreciate any help.
Thank you in advance.
There is no "early" binding in Knockout. Everything is bound when you call ko.applyBindings. But certain bindings can stop or delay binding of their descendant elements. template is one of those when you use the if or ifnot options. In your case, you can use the if option like this:
template: { name: 'dialogFormTemplate', data: CurrentAccount, 'if': CurrentAccount }
Note: The quotes around if are required in some older browsers.

How to dynamically generate options for RichCombo in CKEDITOR?

There is a form on my page with textarea (CKEDITOR) and select field <select id="_photogalleries" multiple="multiple"></select>. I'd like options in RichCombo to depend on the options that are selected in select with id #_photogalleries. Is there any way to regenerate RichCombo dynamically?
Thanks in advance.
CKEDITOR.plugins.add('style_plugin', {
requires: ['richcombo'],
init: function(editor) {
var pluginName = 'style_plugin';
var config = editor.config,
lang = editor.lang.format;
editor.ui.addRichCombo('photogalleries', {
label: "Фоторепортаж",
title: "Фоторепортаж",
voiceLabel: "Фоторепортаж",
className: 'cke_format',
multiSelect: false,
icon: CKEDITOR.plugins.getPath('style_plugin') + 'photo-list-horizontal.png',
panel: {
css: [config.contentsCss, CKEDITOR.getUrl(editor.skinPath + 'editor.css')],
voiceLabel: lang.panelVoiceLabel
},
init: function () {
this.startGroup("Фоторепортаж");
var list=this;
$("#_photogalleries option:selected").each(function(index, value){
console.log(index, value);
list.add("#HORIZONTAL_GALLERY_"+ $(value).val()+"#", "(Г) " + $(value).text(), "(Г) " + $(value).text());
list.add("#VERTICAL_GALLERY_"+ $(value).val()+"#", "(В) " + $(value).text(), "(В) " + $(value).text());
});
},
onClick: function (value) {
editor.focus();
editor.fire('saveSnapshot');
editor.insertHtml(value);
editor.fire('saveSnapshot');
}
});
}
});
This works for me and you dont have to keep a global variable.
CKEDITOR.plugins.add('systemdata', {
init: function (editor) {
var fnData = editor.config.fnData;
if (!fnData || typeof (fnData) != 'function')
throw "You must provide a function to retrieve the list data.";
editor.ui.addRichCombo('systemDataCmb',
{
allowedContent: 'abbr[title]',
label: "System Data",
title: "System Data",
multiSelect: false,
init: function () {
var self = this;
var content = fnData();
$.each(content, function(index, value) {
// value, html, text
self.add(value.name, value.name, value.name)
});
}
}
Then to set the function to get the data put this somewhere where you setup the ckeditor
CKEDITOR.replaceAll(function(element, config) {
config.startupFocus = true;
config.fnData = function() {
var returnData = null;
$.ajax({
url: "/GetData",
async: false,
data: { id: 1 },
}).done(function(result) { returnData= result; });
return returnData;
};
});
It assumes you bring back a json response that has an array of items that have a value property, that can be easily changed though.
I guess I found a solution that worked for me. It was to keep a list object in a global variable and then modify it when onchange event fires in the external select.
I solved this trouble with a single line:
YOURCOMBO.createPanel(editor);
For example:
var comboTeam = editor.ui.get("team");
comboTeam.createPanel(editor);//This is important, if not, doesnt works
Now you can add items to the combo
comboTeam.add("name","name","name");
comboTeam.add("name2","name2","name2");
comboTeam.add("name3","name3","name3");

Categories

Resources