Need to retain dynamically created option in combo box using Knockout.js - javascript

I have a codeset that dynamically creates an "option" in a select box. But, since we're using Knockout, when I go to SELECT that newly created option, and click on it, it gets removed, e.g. DISAPPEARS! Poof!!!!
So, here's the create script:
function createNewGroup()
{
var htmlSelect = document.getElementById('groups');
var optionValue = document.getElementById('newgroupname');
if (optionValue.value === '')
{
alert('Please enter group name.');
optionValue.focus();
return false;
}
if (isOptionAlreadyExist(htmlSelect, optionValue.value))
{
optionValue.value = "";
alert('Group name already exists.\n\nPlease try again.');
optionValue.focus();
return false;
}
var selectBoxOption = document.createElement("option");
selectBoxOption.value = optionValue.value;
selectBoxOption.text = optionValue.value;
htmlSelect.add(selectBoxOption, null);
optionValue.value = "";
alert("New group has been added successfully.");
optionValue.focus();
return true;
};
Since this is a KNOCKOUT observable, how to keep it in the box when I select it, moreover, how do I send that new value back to JSON object. Here's an example of that:
{"groups":[
{
"groupname" : "Administrator",
"attr" : { "id" : "li.attr.node_1",
"href" : "#",
"data-bind" : "click: grpMgmt('Administrator');" }
},
{
"groupname" : "Guest",
"attr" : { "id" : "li.attr.node_2",
"href" : "#",
"data-bind" : "click: grpMgmt('Guest');" }
}
]
}
Hence, the admin user can create a new user so it can look like this:
{"groups":[
{
"groupname" : "Administrator",
"attr" : { "id" : "li.attr.node_1",
"href" : "#",
"data-bind" : "click: grpMgmt('Administrator');" }
},
{
"groupname" : "Guest",
"attr" : { "id" : "li.attr.node_2",
"href" : "#",
"data-bind" : "click: grpMgmt('Guest');" }
}
],
"users":[
{
"groupname" : "Joes Users",
"attr" : { "id" : "li.attr.node_1",
"href" : "#",
"data-bind" : "click: grpMgmt('Joe');" }
}
]
}
OK, I'll stop writing for now... thanks...

If you're using knockout (which I can't actually see) all you need to do is bind your select box to an observable array and when you need to add a new item just push it onto the array and knockout will add it to the list for you.
Knockout should essentially replace that script you've included with a lot less, much more simplistic code.

Related

JavaScript trigger does not work

I try to trigger a button so when user loads a page, the button is automatically clicked.
My code is following:
$(document).ready(function() {
console.log("it's here");
$("#btnPeriod").trigger('click');
});
$("#btnPeriod").on('click', function(){
var ahhhhh = "<security:authentication property="securityUser.fullName"/>";
ahhhhh = ahhhhh.replace(/ /g, " ");
console.log(ahhhhh);
$.extend($("#noticeList").jqGrid("getGridParam", "postData"),{
filters : JSON.stringify({
groupOp : "OR",
rules : [{
field : "notiWriter",
op : "eq",
data : ahhhhh
}],
groups : []
})
});
$("#noticeList").jqGrid("setGridParam", {search : true}).trigger('reloadGrid', [{current : true, page : 1}]);
});
and when the page is loaded, I can see log of "it's here" and value of ahhhhh. However, even though I can see log, the action suppose to be happened does not get applied. Funny thing is when I click the button, then it works, with another log message of variable ahhhhh.
FYI, I am using jqGrid and when I click btnPeriod button, it filters rows that its cellvalue of notiWriter does not match with variable ahhhhh.
For now, when I load this page, it displays like following:
And then, when I click a button, it only shows certain rows like following:
And I hope it always look like second picture when a user loads the page.
I once used setTimeout, but it turned out it did not work well, so I hope you give me some help.
Thank you in advance.
You need to bind the click handler to the button inside the document.ready handler, and before you call trigger(). Try this:
$(document).ready(function() {
$("#btnPeriod").on('click', function(){
var ahhhhh = "<security:authentication property="securityUser.fullName"/>";
ahhhhh = ahhhhh.replace(/ /g, " ");
console.log(ahhhhh);
$.extend($("#noticeList").jqGrid("getGridParam", "postData"),{
filters : JSON.stringify({
groupOp : "OR",
rules : [{
field : "notiWriter",
op : "eq",
data : ahhhhh
}],
groups : []
})
});
$("#noticeList").jqGrid("setGridParam", {
search: true
}).trigger('reloadGrid', [{
current: true,
page: 1
}]);
});
$("#btnPeriod").trigger('click');
});
Try including the event binding inside the jquery ready function and bind the event before trigger the click:
$(document).ready(function() {
console.log("it's here");
$("#btnPeriod").on('click', function(){
var ahhhhh = "<security:authentication property="securityUser.fullName"/>";
ahhhhh = ahhhhh.replace(/ /g, " ");
console.log(ahhhhh);
$.extend($("#noticeList").jqGrid("getGridParam", "postData"),{
filters : JSON.stringify({
groupOp : "OR",
rules : [{
field : "notiWriter",
op : "eq",
data : ahhhhh
}],
groups : []
})
});
$("#noticeList").jqGrid("setGridParam", {search : true}).trigger('reloadGrid', [{current : true, page : 1}]);
});
$("#btnPeriod").trigger('click');
});
Why not including the click event binding inside your ready function ?
$(document).ready(function() {
console.log("it's here");
$("#btnPeriod").on('click', function() {
var ahhhhh = "<security:authentication property="securityUser.fullName"/>";
ahhhhh = ahhhhh.replace(/ /g, " ");
console.log(ahhhhh);
$.extend($("#noticeList").jqGrid("getGridParam", "postData"), {
filters : JSON.stringify({
groupOp : "OR",
rules : [{
field : "notiWriter",
op : "eq",
data : ahhhhh
}],
groups : []
})
});
$("#noticeList").jqGrid("setGridParam", {search : true}).trigger('reloadGrid', [{current : true, page : 1}]);
});
$("#btnPeriod").trigger('click');
});

ExtJS make one combo item different

Maybe someone can give some ideas, how to add item to the end of combobox dropdown, and make it "different" for example put separator before it or make it bold. Combobox uses sorted (by name) store, and on load there is added item which I want to make different.
Ext.define('Plugin.workspace.store.FavouriteCarStore', {
extend : 'Plugin.workspace.store.CarStore',
alias : 'store.favouritecar',
filters : [{
property : 'favorite',
value : true
}],
listeners : {
load : function(store) {
var rec = {
id : 'showAll',
name : 'Show All',
favorite : true
};
store.add(rec);
}
}
});
combo uses this store:
tbar : [{
xtype : 'combo',
width : 200,
editable: false,
store : {
type : 'favouritecar'
},
bind : {
value : '{workspace}'
},
tpl : '<ul class="x-list-plain"><tpl for="."><li role="option" class="x-boundlist-item">{name}</li></tpl></ul>',
displayTpl : '<tpl for=".">{name}</tpl>',
listeners : {
'select' : 'onSelectWorkspace'
}
}].
This code adds item, which looks like others, and places it depending on sort.
I use 5.1 ExtJS.
EDIT: solution to add item to list end.
sorters : [{
sorterFn : function(rec1, rec2) {
if (rec1.id != 'showAll' && rec2.id != 'showAll') {
return ((rec1.get('name') > rec2.get('name')) ? 1 : (rec1.get('name') === rec2.get('name') ? 0 : -1));
} else {
return ((rec1.id == 'showAll') ? 1 : -1);
}
}
}],
Method 1
Use a custom cls on the combo's listConfig:
listConfig: {
cls: 'thisComboMakesLastItemDifferent'
},
And then use CSS to make the last item different:
.thisComboMakesLastItemDifferent li:last-child {
color: red;
font-weight: bold;
}
Method 2
Since you are marking your "different" item with favorite: true, you can code it in the template:
tpl: '<tpl for="."><li role="option" class="x-boundlist-item favorite-{favorite}">{name}</li></tpl>',
And then, again, use CSS:
.favorite-true:before {
content: 'FAV: '
}
Note that the first method focuses on making the last item different regardless of what item it is. The second method makes specific item different (you need extra logic to make sure it is the last; you have one already).
See both methods in action: https://fiddle.sencha.com/#fiddle/sdj
Maybe you can use store.insert(store.indexOf(store.last()) index, rec) or store.insert(store.count() - 1, rec)?
load : function(store) {
somewhere.static.setShowAllAsLastRecordOfStore(store);
}
filterchange(store, filters, eOpts) {
somewhere.static.setShowAllAsLastRecordOfStore(store);
}
sort(store, eOpts) {
somewhere.static.setShowAllAsLastRecordOfStore(store);
}
setShowAllAsLastRecordOfStore: function(store) {
var rec = {
id : 'showAll',
name : 'Show All',
favorite : true
};
store.remove(store.findRecord('id', 'showAll'));
store.insert(store.indexOf(store.last()) index, rec);
// or
store.insert(store.count() - 1, rec);
}

How to create create JSON object ( of form elements) of dynamic html form?

Trying to create dynamic HTML forms and save them, I can create dynamic forms using bootstrap but on submit i am struggling to create JSON of this dynamic form.
I am looking to save something like this
{
"form" :
[
{
"name" : "username",
"id" : "txt-username",
"caption" : "Username",
"type" : "text",
"placeholder" : "E.g. user#example.com"
},
{
"name" : "password",
"caption" : "Password",
"type" : "password"
},
{
"type" : "submit",
"value" : "Login"
}
]
}
I am not sure how i can achieve this.
This should do it:
function getAttrs(DOMelement) {
var obj = {};
$.each(DOMelement.attributes, function () {
if (this.specified) {
obj[this.name] = this.value;
}
});
return obj;
}
$("form").each(function () {
var json = {
"form": []
};
$(this).find("input").each(function () {
json.form.push(getAttrs(this));
});
$(this).find("select").each(function () {
var select = getAttrs(this);
select["type"] = "select";
var options = [];
$(this).children().each(function () {
options.push(getAttrs(this));
});
select["options"] = options;
json.form.push(select);
});
console.log(json);
});
DEMO: http://jsfiddle.net/j1g5jog0/
Update: http://jsfiddle.net/j1g5jog0/5/

jsTree disable checkbox not working

I am using jsTree latest version in one of my application.
I want certain checkboxes to be disabled by default.
For that i am referring this.
I have following jstree code:
$("#"+"div_"+aspectid).jstree({
'core' : {
"themes" : { "icons" : false },
'data' : {
'url' : 'include/ajax.php?option=constructtree',
'data' : function (node) {
return { aspectcode : aspectcode, geographylevel : geographylevel };
}
}
},
"types" :
{
"types" : {
"disabled" : {
"check_node" : false,
"uncheck_node" : false
}
}
},
"plugins" : ["themes","html_data","ui","crrm","types", "checkbox"],
"checkbox" : { "two_state" : true }
});
I have added rel=disabled in the li tags
<li id=$childvalue[code] rel='disabled'>
I am not getting any errors and i am able to check and uncheck the node.
What could be the issue?
provide filddler for same.
Inorder to disable check box and make it not to check and uncheck use "onclick= return false"
This functionality has been changed in more recent versions of jstree.
With 3.2, to disable a checkbox set the data-jstree attribute on the LI tag.
<li data-jstree={ "checkbox_disabled": true }>

jstree remove default elements from context menu

I have a problem with JsTree's contextmenu, how can I remove the default elements from the contextmenu like Create, Delete, Rename? I want to provide elements of my own, but the default elements are still at the contextmenu.
"contextmenu" : {
"items" : {
"IsimVer" : {
"label" : "İsim Değiştir",
"action" : function (obj) { this.rename(obj); }
},
"Ekle" : {
"label" : "Ekle",
"action" : function (obj) { this.create(obj); }
},
"Sil" : {
"label" : "Sil",
"action" : function (obj) { this.remove(obj); }
}
}
I had this issue a couple of days ago but haven't yet decided if this is a bug or a feature. It may be related to the order in which the plugins are loaded.
What worked for me was returning the items from a function:
"contextmenu" : {
"items" : function ($node) {
return {
"IsimVer" : {
"label" : "İsim Değiştir",
"action" : function (obj) { this.rename(obj); }
},
"Ekle" : {
"label" : "Ekle",
"action" : function (obj) { this.create(obj); }
},
"Sil" : {
"label" : "Sil",
"action" : function (obj) { this.remove(obj); }
}
};
}
}
After some searching it seems that the default behaviour is for your menu items to extend the defaults, so this is a feature. Unfortunately the documentation currently lacks the detail on this point.
If you like to modify labels of existing items or remove a few, a simple solution like below will work
"contextmenu": {
"items": function(node) {
var defaultItems = $.jstree.defaults.contextmenu.items();
defaultItems.create.label = "Ekle";
delete defaultItems.ccp;
return defaultItems;
}
}
This will set "Create" items label as "Ekle" and remove cut copy paste from default items.
Just set value to false in items object. For example, to disable edit (cut, copy, paste) menu try this:
contextmenu : {
items : {
"ccp" : false
}
}
Set ccp, create, rename, remove to false like this :
plugins : ["themes","json_data","ui","crrm", "hotkeys", "types", "contextmenu"],
contextmenu : {
items : {
"IsimVer" : {
"label" : "IsimVer",
"action" : function (obj) { alert("IsimVer"); }
},
"Ekle" : {
"label" : "Ekle",
"action" : function (obj) { alert("Ekle"); }
},
"Sil" : {
"label" : "Sil",
"action" : function (obj) { alert("tiga"); }
},
"ccp" : false,
"create" : false,
"rename" : false,
"remove" : false
}
}

Categories

Resources