populate HTML form elements from object by jQuery - javascript

My from elements are written in Object. I need to populate HTML form elements from that. Problem is that Object contains different input types, structure, custom rules etc. For example, there will be text input, image type input, select box, radio, checkbox etc. So, I don't understand looping over the object will be good idea (I started this, but couldn't complete by myself :( ). I could write the html tag element in html file too. But, I must take the value from that object. So, what's the best solution for it?
Sample Object:
var formObj = {
username: {
value: null,
type: 'text',
placeholder: 'Enter username'
},
password: {
value: null,
type: 'password',
placeholder: 'enter password'
},
country: {
value: null,
type: 'select',
defaultText: 'Choose here',
option: [
{
value: '1',
label: 'Australia'
},
{
value: '2',
label: 'USA'
},
{
value: '3',
label: 'UK'
}
]
},
gender: {
value: null,
type: 'select',
defaultText: null,
option: [
{
value: 'male',
label: 'Male'
},
{
value: 'female',
label: 'Female'
},
{
value: 'other',
label: 'Other'
}
]
}
}
jsfiddle demo

your jsfiddle demo revised
Added some comments to your demo. I'd also look into template strings. They'll make your life easier and code cleaner :) and the single responsibility principle for breaking your code into easier to manage/read pieces.
var html = ''; // <-- Initialize as empty string for `+=`
$.each(formObj, function(key, value) {
if (value.value === null) {
value.value = '';
}
// Add label
html += '<label for="' + key + '">' + key + '</label>';
// Add input
if (value.type === 'select') {
// Type is select
html += '<select class="form-control">' + generateOptionPlaceholder(value.defaultText) + generateOptionMarkup(value.option) + '</select>';
} else {
html += '<input name="' + key + '" type="' + value.type + '" value="' + value.value + '" placeholder="' + value.placeholder + '" class="form-control" />';
}
console.log(html);
});

You could use a strategy pattern for this sort of thing. For any variance, used a dictionary where the keys are based off of the variant, and the values are a function to call for that variant.
For example, if your object with form data had a structure like this:
var form = {
"field1": {
type: "text"
value: "foo",
attrs: {...}
},
...
}
You can use a strategy to handle different field types. Your strategy dictionary might start our like this:
var FIELD_STRATEGY = {
"input": function (name, value, attrs) {
// General purpose method for <input>
// Needs type included in attrs
"text": function (name, value, attrs) {
// Constructs an <input type="text">
attrs.type = "text";
return FIELD_STRATEGY.input(name, value, attrs);
},
"option": function (value, label, attrs) {
// Constructs an <option>
},
"select": function (name, options, attrs {
// Constructs a <select>
var opts = options.map(function(opt) {
return FIELD_STRATEGY.option(
null,
opt.value,
opt.label);
}).join("");
var attr_str = Object.keys(attrs).map(function(attr) {
var value = attrs[attr];
return name + '="' + value '"';
}).join(" ");
return '<select name="' + name + '" ' + attr_str + '>' +
opts + '</select>';
}
};
To use it, loop over the field names and invoke strategies based on type:
var fields = Object.keys(form).map(function (name) {
var conf = form[name] || {};
var strategy = FIELD_STRATEGY[conf.type];
var rendered = "";
if (strategy) {
rendered = strategy(name, conf.value, conf.attrs);
}
return rendered;
});
This will give you a final fields list containing rendered strings based on the strategy for each field type.

Related

Get labelField text and form field values together

I intend to build a text with the text of labelField and textfield value
In my fiddle example the text of the fieldLabel is created dynamically.
what I want to achieve is to generate a text with the text of fielLabel and the value of the textfield.
https://fiddle.sencha.com/#fiddle/1icj
As is the fiddle displays "Homer, Simpson"
What I want to achieve: "Name Homer, Last Name Simpson"
It seems to me there is no method which gives the value of fieldLabel.
How to achieve this?
It is possible in some way, using binding?
What if I use a custom property, it is possible to obtain its value?
buttons: [{
text: 'GetValues',
handler: function() {
var formValues = this.up('form').getForm().getValues();
console.log(formValues);
var finalValues = [];
var needsLineBreak = false;
if (formValues != null) {
var form=this.up('form'),
index=0;
Ext.iterate(formValues,function(key,val){
finalValues += form.getComponent(index).getFieldLabel()+':';
finalValues += val + ',';
index++;
});
finalValues=finalValues.slice(finalValues.lenght,-1);
}
console.log(finalValues);
}
}],
you can use getter/setter to achieve this functionality
items: [{
fieldLabel: labelName,
name: 'first',
get value(){
return this.fieldLabel +' Homer';
},
allowBlank: false,
myCustomProp: labelName
},{
fieldLabel: labelLastName,
name: 'last',
get value(){
return this.fieldLabel +' Simpson';
},
allowBlank: false
}],

Getting repeated values inside dropdown

I am having a dropdown which is fetching values from json but as my json file having some repeated values so I want them only once ..before it was working fine as I was able to filter the values but when I included some more code it started again taking repeated values ..please have alook..Thank you..
$(document).ready(function() {
Variable usednames is filtering the values..
$.ajax({
url: "data.json,
dataType: "json",
success: function(obj) {
var jsObject = obj;
var usedNames = [];
$('<option>', {
text: 'Select your Option',
value: '',
selected: 'selected',
disabled: 'disabled'
}).appendTo('#dropdown1');
$('<option>', {
text: 'Select your List Option',
value: '',
selected: 'selected',
disabled: 'disabled'
}).appendTo('#checkbox');
$.each(obj, function(key, value) {
if (usedNames.indexOf(value.name) == -1) {
$("#dropdown1").append("<option value=" + key + ">" + value.name + "</option>");
usedNames.push(value.name);
}
/* $('<option>', {
text: 'Select your Option',
value: '',
selected: 'selected',
disabled: 'disabled'
}).appendTo('#dropdown1');
*/
$.each(usedNames, function(index, value) {
$('<option>', {
text: value['name'],
value: index
}).appendTo('#dropdown1');
});
/* $('<option>', {
text: 'Select your List Option',
value: '',
selected: 'selected',
disabled: 'disabled'
}).appendTo('#listbox');
*/
$('#dropdown1').change(function() {
$('#checkbox').empty();
$('<option>', {
text: 'Select your List Option',
value: '',
selected: 'selected',
disabled: 'disabled'
}).appendTo('#checkbox');
var selection = $('#dropdown1 :selected').text();
$.each(jsObject, function(index, value) {
if (value['name'] === selection) {
$('<option>', {
text: value['attr001'],
value: 'attr001'
}).appendTo('#checkbox');
$('<option>', {
text: value['attr002'],
value: 'attr002'
}).appendTo('#checkbox');
$('<option>', {
text: value['attr003'],
value: 'attr003'
}).appendTo('#checkbox');
My HTML file
<form name="myform" id="myForm">
<select id="dropdown1"></select>
<!-- <select id="listbox"></select> -->
<input type="checkbox">
<br>
I think I see why. You have this code :
if (usedNames.indexOf(value.name) == -1) {
$("#dropdown1").append("<option value=" + key + ">" + value.name + "</option>");
usedNames.push(value.name);
}
Which works (or should work) just fine. But after that, you have this :
$.each(jsObject, function(index, value) {
$('<option>', {
text: value['name'],
value: index
}).appendTo('#dropdown1');
});
By having a look at your code, it seems that jsObject is equal to obj. So, in the first part, you're indeed checking for repeated values, that you put in the array named usedNames.
But shortly after, you're appending jsObject to #dropdown1, so you're never using the array usedNames, which should only have unique values.
You should use usedNames after creating it, and forget about obj or jsObject, unless it caries some more information.
EDIT : Note that, when creating usedNames, you're also appending to your dropdown. So you're appending what will be the content of usedNames, and then appending jsObject.
You could fill a list of unique values before assigning it to the dropdown.
function unique(arr) {
var u = {}, a = [];
for(var i = 0, l = arr.length; i < l; ++i){
if(!u.hasOwnProperty(arr[i])) {
a.push(arr[i]);
u[arr[i]] = 1;
}
}
return a;
}
Most elegant way to create a list of unique items in JavaScript

Multiple Column returns undefined in MVC using MCAutocomplete Jquery UI

my multiple column in mvc returns undefined.
what do i missed? or there is wrong with my code? pls help.
Controller
public ActionResult EmployeeIDSearch(string term)
{
// Get Tags from database
using (var ctx = new DASH_FAEntities())
{
var tags = (from e in ctx.EmployeeMasters
where e.EMT_EmployeeID.ToLower().Contains(term.ToLower().Trim())
select new
{
EmployeeID = e.EMT_EmployeeID.Trim(),
FullName = e.EMT_FirstName.Trim() + " " + e.EMT_LastName.Trim(),
Department = e.EMT_Department.Trim()
}).ToArray();
return Json(tags, JsonRequestBehavior.AllowGet);
}
}
View
#Html.TextBox("EmployeeID", null, new { #class = "form-control", #placeholder = "Employee ID", #id="employeeid" })
Jquery
function customRenderItem(ul, item) {
var t = '<span class="mcacCol1">' + item[0] + '</span><span class="mcacCol2">' + item[1] + '</span><span class="mcacCol3">' + item[2] + '</span>',
result = $('<li class="ui-menu-item" role="menuitem"></li>')
.data('item.autocomplete', item)
.append('<a class="ui-corner-all" style="position:relative;" tabindex="-1">' + t + '</a>')
.appendTo(ul);
return result;
}
var columns = [{ name: 'Employee ID', minWidth: '100px' }, { name: 'Full Name', minWidth: '100px' }, { name: 'Department', minWidth: '100px' }]
$("#employeeid").mcautocomplete({
showHeader: true,
columns: columns,
source: '#Url.Action("EmployeeIDSearch", "Home")',
select: function (event, ui) {
this.value = (ui.item ? ui.item[0] : '');
return false;
}
});
mcautocomplete.js
I already checked the jsfiddle file of this plugin. I only just change the source and added another column. But still undefined when I look for the employee id.
I break point my controller where I get my source and it has a value every time I time for employee id.
Also I've already googled and i found nothing. It's been yesterday and I don't know what to do. I don't want to use other plugin because my web would be slow for using different plugin.
Please Help.
From the documentation, the syntax your using for the columns property is only suuitable if the source is an array of arrays. For example it would work it the data was
[['1', 'Joe Blogs', 'Administration'], ['2', 'John Doe', 'Finance']]
but your controller method is returning an array of objects, so you need to also specify the valueField property. Change the columns definition to
var columns = [{ name: 'Employee ID', minWidth: '100px', valueField: 'EmployeeID' },
{ name: 'Full Name', minWidth: '100px', valueField: 'FullName' },
{ name: 'Department', minWidth: '100px', valueField: 'Department' }]
where the value of valueField match the property name.
Edit
Since you now adding objects, not arrays, you also need to change
this.value = (ui.item ? ui.item[0] : '');
to
this.value = (ui.item ? ui.item.EmployeeID : '');
in order to display the selected value in the textbox (refer updated fiddle for a working example).

How to customize output of the field with UI Grid

I have a set of fields or each row looking like
{inBing:true, inOSM:true, inGoogle:false}.
Depending on these I want to represent these values as a string, like 'B O', meaning Bing and OSM are enabled and Google is not.
So I need to go through these fields and build an output string.
The question is where can I put and call this function in UI grid?
I'd use a filter for this.
Manipulate your data to look like:
{ field1: value1, field2: value2, searchFlags: { inBing: true, inOSM: false, inGoogle: true } }
{ field1: value2, field2: value4, searchFlags: { inBing: false, inOSM: true, inGoogle: false } }
...
And your columnDefs like:
columnDefs: [
{ name: 'field1' },
{ name: 'field2' },
{ name: 'searchFlags', cellFilter: 'mapFlags' }
];
Finally, define the filter:
.filter('mapFlags', function( input ) {
str = '';
if (v.inBing) str += 'B ';
if (v.inOSM) str += 'O ';
if (v.inGoogle) str += 'G';
return str;
});
There is an example of a filter in http://ui-grid.info/docs/#/tutorial/201_editable
could use a custom cell template like this:
columnDefs: [
{ name: 'name' },
...
{ name: 'whichSearchEngines', field: 'some_field', cellTemplate: '<div class="ui-grid-cell-contents" >{{grid.appScope.searchEngineFormatter(row.some_field)}}</div>' }
]
$scope.searchEngineFormatter = function (v) {
str = '';
if (v.inBing) str += 'B ';
if (v.inOSM) str += 'O ';
if (v.inGoogle) str += 'G';
return str;
};

Select2.js: why is id the same as text on change for removed?

JSfiddle: http://jsfiddle.net/cjVSj/
I have a simple select2 with the range of possible tags set by the tags option and the preloaded tags set by values in the input field in the html.
When the on change event fires on the select2, the removed item seems to lose its id, reporting instead its text value.
To see the problem, adding a tag (e.g. west) correctly reports the added.id, but removing the existing east tags reports id = east, not 1356.
Any insight into how to gain access to the id of a tag upon removal?
HTML:
<script>
var tags = [{ "id": 1354, "text": "north", "restricted": false
}, {"id": 1355, "text": "south", "restricted": false
}, {"id": 1356, "text": "east", "restricted": false
}, {"id": 1357, "text": "west", "restricted": false
}];
</script>tags:
<input type="text" id="mytags" value="east" />
JS:
$(document).ready(function () {
$('#mytags').select2({
placeholder: 'Search',
allowClear: true,
minimumInputLength: 2,
multiple: true,
tags: tags,
tokenSeparators: [','],
});
$('#mytags').on("change", function (e) {
console.log("change " + JSON.stringify({
val: e.val,
added: e.added,
removed: e.removed
}));
if (e.added) {
alert('added: ' + e.added.text + ' id ' + e.added.id)
} else if (e.removed) {
alert('removed: ' + e.removed.text + ' id ' + e.removed.id)
}
});
});
There was an issue with your select2 declaration and syntax.
Further more, if you entered any other text, say "eas" or "test", your piece of code reflected that as it is. Check this scenario.
Updated fiddle: http://jsfiddle.net/ZBf5H/
To be specific, you did not give appropriate mapping to your tags. Please find how to access remote data in select 2 from here
The change of code is as below:
$(document).ready(function() {
var data=[{id:1354,text:'north',restricted:false},
{id:1356,text:'east',restricted:false},
{id:1357,text:'west',restricted:false},
{id:1355,text:'south',restricted:false}];
function format(item)
{ return item.text; }
$('#mytags').select2({
placeholder: 'Search',
allowClear: true,
minimumInputLength: 2,
multiple: true,
tags: tags,
tokenSeparators: [','],
data:{ results: data, text: 'text' },
formatSelection: format,
formatResult: format
});
Let me know if this works for you.
Ok... I've got a working solution, but I still don't exactly understand the difference between select2's tags and data options....
JSfiddle: http://jsfiddle.net/7e8Pa/
I'm initializing select2 with a list of all possible tags via the data option from an array, then selecting those for preloading: the initSelection function checks for ids in the and looks them up in the data array (the pre-stored one, not Select2's). Last, new tags may be added (the createSearchChoice does this). To hook this to my server, I'm just going to insert ajax calls where noted below in the on-change event handler (which gets called after createSearchChoice, and can overwrite the field values for the new object set in createSearchChoice).
JS:
function findWithAttr(array, attr, value) {
for (var i = 0; i < array.length; i += 1) {
if (array[i][attr] == value) {
return array[i];
}
}
}
$(document).ready(function () {
function format(item) {
return item.text;
}
$('#mytags').select2({
placeholder: 'Search',
minimumInputLength: 2,
multiple: true,
//tags: tags,
tokenSeparators: [','],
data: {
results: tags,
text: 'text'
},
initSelection: function (element, callback) {
var data = [];
$($('#mytags').val().split(",")).each(function (i) {
var o = findWithAttr(tags, 'id', this);
if (o) {
data.push({
id: o.id,
text: o.text
});
} else {
console.log("findWithAttr returned none; likely invalid id");
}
});
console.log("data = " + JSON.stringify(data));
callback(data);
},
createSearchChoice: function (term, data) {
console.log("create");
if ($(data).filter(function () {
return this.text.localeCompare(term) === 0;
}).length === 0) {
// call $.post() to add this term to the server, receive back id
// return {id:id, text:term}
// or detect this shiftiness and do it below in the on-change
return {
id: -1,
text: term
};
}
},
formatSelection: format,
formatResult: format
});
$('#mytags').on("change", function (e) {
console.log("change " + JSON.stringify({
val: e.val,
added: e.added,
removed: e.removed
}));
if (e.added) {
alert('added: ' + e.added.text + ' id ' + e.added.id);
//modifying the id here overrides what is assigned above in createSelection
e.added.id = 5;
} else if (e.removed) {
alert('removed: ' + e.removed.text + ' id ' + e.removed.id);
}
var selections = (JSON.stringify($('#mytags').select2('data')));
$('#selectedText').text(selections);
});
});
HTML:
<script>
var tags = [{
"id": 1354,
"text": "north",
"restricted": false
}, {
"id": 1355,
"text": "south",
"restricted": false
}, {
"id": 1356,
"text": "east",
"restricted": false
}, {
"id": 1357,
"text": "west",
"restricted": false
}];
</script>
<p>tags:
<input type="text" id="mytags" value="1355" style="width:80%" />
</p>
<p>Selected Options: <span id="selectedText"></span>
</p>
<p>Debug: <span id="debug"></span>
</p>

Categories