I am working on code where user selects an item from dropdown list and the UI elements are displayed according to that selected item. Example: if item1 is selected there will be 2 textboxes, 1 textarea and a checkbox. item2 will have 1 textbox. etc.
So, I currently have a function where I add html elements according to item selected. I get a JSON file where there is list of items and what UI elements are required for that item. When user selects an item I get the required information from that JSON file and call following code:
$scope.myHTML = "";
var aForm = (angular.element(document.getElementById('appType')));
aForm.html('');
dropdown.forEach(function(viewItem, index){
if(viewItem.control_type === "TextBox"){
$scope.myHTML += '<label class="label">'+ viewItem.label +'</label>'+
'<input type="text" ng-model = "item.value'+index + '" placeholder = "'+ viewItem.text +'">';
}
if(viewItem.control_type === "TextArea"){
$scope.myHTML += '<label class="label">'+ viewItem.label +'</label>'+
'<textarea type="text" rows="4" ng-model = "tests.value'+index + '" ></textarea>'';
}
}
aForm.append($scope.myHTML);
$compile(aForm)($scope);
So the ng-model will have item.value0,item.value1 and so on for each element. I have used $compile to add the html view to UI.
The problem is that I can get the values in my controller but I cannot set those values from controller.
dropdown.forEach(function(viewItem, index){
$scope.tests['value'+index] = "SomePresetValue"; //Does not update value on HTML
});
Does not set value to the HTML element. I tried the following after searching for alternate solutions but did not work.
$scope.$apply(function(){
dropdown.forEach(function(viewItem, index){
$scope.item['value'+index] = viewItem.value;
});
});
Related
This is my fiddle : DEMO
I am adding the template ID read-only fields, based on selection of option. 1 for SMS, 2 for email etc..
Since there is a provision to add new category, how to dynamically add template IDs to newly added options?
//Adding Template ID based on option
$('#categoryevent').on('click', function() {
$('.actionConfig').empty();
var z = $("#categoryevent option:selected").text();
if (z == 'sms') {
var smsConfig = '<div class=form-group><label class="col-sm-2 control-label"for=templateId>Template ID: </label><div class=col-sm-8><input class=form-control id=templateId name=templateId value="1" readonly="readonly"></div></div>';
$('.actionConfig').append(smsConfig);
}
});
Instead of checking for the textual representation of the option, you should check for the value attribute. Since you did not add the value attributes yet for the options you hardcoded, you will have to do this as well, i.e. change:
<option>SMS</option>
to
<option value="0">SMS</option>
Alternatively, if you don't want to use the standard value attribute (e.g. because you want to avoid default beheviour) you can instead go for <option data-selectionId="1">SMS</option>. Obviously increment the id for each option you have in your select.
Now if you create a new option, you will have to set this data:
var val = $("#new-option-event").val().trim();
var opt = '<option value="'+ globalCounterVariable +'">' + val + '</option>';
globalCounterVariable += 1;
$('#categoryevent').append(opt);
$('#categoryevent').val(val);
$('#new-option-event').val('');
You will have to define a global veriable (actually outside of the scope of the .addevent handler is enough) that you initially will have to set to 3 (the number of hardcoded options).
Now you can do this:
$('#categoryevent').on('change', function() {
var selection = $(this).val(); //this is reference to the changed element, i.e. the select with Id 'categoryeveny'.
var html = '<div class="form-group"><label class="col-sm-2 control-label" for="templateId">Template ID: </label><div class="col-sm-8"><input class="form-control" id="templateId" name="templateId" readonly="readonly"></div></div>';
$(html).find("input").val(selection);
$(".actionConfig").empty();
$('.actionConfig').append(html);
});
Note how I removed the need for all the if clauses, because you did the same logic each branch. Simply parameterize whatever you want to inject and this is all you need.
If you want to show different values for each selection (so different data than 1,2,3,... etc), you will have to either make that an option in the input where you create a new option, or hardcode generic logic in the change event, where you decide what content is shown based on the value of selection.
Welcome to SO,
you can do something like this,
Set value of option as Template-Id 1,2,3 now when you add new category maintain counter and add it as value of newly added option.
Now keep other things same just get template id from option value.
something like this,
var opval = get option value here..
var smsConfig = '<div class=form-group><label class="col-sm-2 control-label"for=templateId>Template ID: </label><div class=col-sm-8><input class=form-control id=templateId name=templateId value="+opval+" readonly="readonly"></div></div>';
$('.actionConfig').append(smsConfig);
Hope this helps.
Edit:
answer jsfiddle
Here is the answer fiddle : DEMOanswer
$('#categoryevent').on("click", function(ev) {
// alert(ev.target.selectedIndex);
var value = ev.target.selectedIndex;
$('.actionConfig').empty();
var z = $("#categoryevent option:selected").text();
z = z.toLowerCase();
var templateId = '<div class=form-group><label class="col-sm-2 control-label"for=templateId>Template ID: </label><div class=col-sm-8><input class=form-control id=templateId value="' + value + '" name=templateId readonly="readonly"></div></div>';
$('.actionConfig').append(templateId);
});
I am creating a div dynamically with ajax. Now if the ajax call is success then i created a string for div element and append it to the original div id.
here is my code
$.ajax({
type:"GET",
url:"resources/json/asnData.json",
dataType:"json",
success:function(data){
$.each(data.Payload, function(index, val){
i=i+1;
stmt+='<div class="row">'+
'<section class="col col-2">'+
'<label class="input"><i class="icon-append fa fa-key"></i>'+
'<input type="text" name="keyName" value="'+val.key+'" readonly/>'+
'</label>'+
'</section>'+
'<section class="col col-3">'+
'<label class="select">'+
'<select id="dataConversionType'+i+'" class="dataConversionType">'+
'<option value="HEX">HEX</option>'+
'<option value="ALL">Compare All</option>'+
'<option value="ASCII">ASCII</option>'+
'<option value="STRING">STRING</option>'+
'<option value="INT">INTEGER</option>'+
'<option value="BINT">BIG INTEGER</option>'+
'</select><i></i>'+
'</label>'+
'</section>'+
'<section class="col col-5">'+
'<label class="input"><i class="icon-append fa fa-dashcube "></i>'+
'<input id="convertedType'+i+'" type="text" value="'+val.value+'" readonly/>'+
'</label>'+
'</section>'+
'</div>';
});
$(".dataParser").append(stmt);
Now there is function where if someone select a value in selectbox then fire and show.
$('#dataConversionType'+i).change(function(e) {
e.preventDefault();
var conversionType=$(this).val(); //I have doubt here also..
console.log(conversionType);
if(conversionType == 'ALL') {
console.log('ALL-Show a modal with each possible conversion');
}
but this is not working. this function works if I called using the class name. But i have to call the function using id with the i value, so that with that i value i can also set some value in other fields.
any help will be appreciated...
Use class instead of id (replace document with some non dynamic container)
$(document).on('change','.dataConversionType',function(e) {
e.preventDefault();
var conversionType=$(this).val();
console.log(conversionType);
var index_val = $(this).attr('data-index')
if(conversionType == 'ALL') {
console.log('ALL-Show a modal with each possible conversion');
}
)};
And when you are generating your element add a data attribute
'<select id="dataConversionType'+i+'" class="dataConversionType" data-index="'+i+'">'
Also if you are inside a loop you need to wrap your ajax within a closure if you want to get correct value and not the latest one.
(function(idx) {
//ajax stuff here
}(i)
Do one thing, Listen to the change event using class name itself, instead of Id.
Put value of i as a custom attribute into the select box. In the listener function, read this attribute and call or perform whatever actions you have to do.
A sample is as below:
'<section class="col col-3">'+
'<label class="select">'+
'<select id="dataConversionType'+i+'" class="dataConversionType" data-count=i>'+
'<option value="HEX">HEX</option>'+
'<option value="ALL">Compare All</option>'+
'<option value="ASCII">ASCII</option>'+
'<option value="STRING">STRING</option>'+
'<option value="INT">INTEGER</option>'+
'<option value="BINT">BIG INTEGER</option>'+
'</select><i></i>'+
'</label>'+
'</section>'
Event listener:-
$('.dataConversionType').change(function(e) {
e.preventDefault();
var conversionType=$(this).val(); //selected value
var valueofI = $(this).attr("data-count");// Value of i
}
data-count is the custom attribute.
Try On change method
$(document).on('change','.dataConversionType',function(e) {
// Paste Your Code
});
OR
$(document).on('change','#dataConversionType',function(e) {
// Paste Your Code
});
$('#dataConversionType1').change(function(e) {alert("Changed")});
this code will not work for dynamically append select box.
you should try-
$(document).on("change","#dataConversionType1",function(){
alert($('#dataConversionType1 option:selected').val());
});
This works for me.
The value of i has been now changed to the latest one and this would not give you all the selectboxes anyways.
If you want to be specific about any select box, do it like:
$('#dataConversionType1').change(function(e) {
// code here
});
If you want to do something on all the selectboxes you have created, you can do it like:
$('[id^="dataConversionType"]').change(function (e) {
// Find the index: Count of i
var elmIndex = $(this).attr("id").replace("dataConversionType", "");
// Reflects the value of it in related input field
$("#convertedType3" + elmIndex).val($(this).val());
});
If you want to use the value of i later for operations, you can do it in 2 ways:
set the value of i in some data- attribute like: data-index=i (example below):
'<select id="dataConversionType'+i+'" class="dataConversionType" data-index="' + i + '">'+
Get the index from the id itself doing split or regex (example: /\d/).
Good morning Stack Overflow,
This will be my first question and I am still learning coding, so please forgive me if I'm ever being naive.
I am currently working on a modal that the user is shown when they're trying to pick quantities of a certain product from a warehouse that has been stored in multiple locations.
The user is given a requested quantity and the drop down menu shows each of the possible locations that they can retrieve an item from. The user will then select the location using the select menu and then adjust the slider with the amount they want to take from that location.
If the user wants to split the requested amount across multiple locations however, they will click the "Pick Another Location" button and another row containing the select menu will appear directly underneath. The user will be able to do this until the total picked has reached the Quantity Requested or until they run out of locations to pick from. My problem is, I am trying to remove the location the user selected prior to clicking the "Pick Another Location" button.
As you can see the same location appears again in the appended menu. I would like to have it so it doesn't. Its turning out to be quite difficult for me because each location picker has a unique ID that is created with a variable and I find it difficult to implement that into any types of condition usually.
I had a similar issue with the Quantity slider, as I was trying to treat each slider individually, but also contribute as a collective. Anyway, starting to get off topic and ramble.
I will show below the code which I feel may help...
Initial creation and variables declared:
//Multiple Location PopUp Function
jQuery.LocPick = function LocPick(id){
//Function Post
$.post(base_url+"ts/TestedQtyMultiLoc/", {
ID: id,
BatchID: $("#BatchID").val()},
//Calling variables to be displayed within the PopUp
function(data){
QtyReq = data.item.QtyRequested;
var code= data.item.ItemCode;
rowCount = $('#AddLocationPicker tr').length;
loc='';
$.each(data.Locations, function(i, value) {loc +='<option value="'+ value.Location + '">' + value.Location + ' -- Qty: ' +value.Qty +'</option>';
})
Picker=0;
This is the code for the HTML contents of my modal:
//PopUp Contents
$("#dialog-ProcessConfirm").html('<p>'+code+' has multiple locations<br><br>Please confirm which locations the item is to be picked from before continuing.</p><p><table id="AddLocationPicker"><tr><td></td><td>Location</td><td>Qty Picked</td></tr><tr id="' + Picker +'"><td></td><td><select class="selectbox" id="LocationPickerSelect'+ Picker +'"><option value="0">Please select a location'+loc+'</option></select></td><td><input class= "QtyPicker" id="AddLocQtyPick'+ Picker +'"type="number" min="1" max='+QtyReq+' value="1" onkeydown="return false"></td></tr></table><table><td></td><td>Quantity Requested:</td><td>'+QtyReq+'</td></table><table><td></td><td><input type="text" name="LocErr" id="LocErr" maxlength="50" size="50" tabstop="false" readonly="true" style="border:0px;color:#FF0000;" value=""><input type="text" name="QtyErr" id="QtyErr" maxlength="50" size="50" tabstop="false" readonly="true" style="border:0px;color:#FF0000;" value=""></td></table></p>');
}, "json");
The "Pick Another Location Button":
//Buttons for the PopUp
buttons: {
'Pick Another Location': function() { //Button to allow user to add another location to pick from
$('#AddLocQtyPick'+Picker).prop ('disabled', true); //Disables the current selection, so that it cannot be edited
$('#LocationPickerSelect'+ Picker).prop ('disabled', true); //Disables the current selection, so that it cannot be edited
Picker++; //Adds Unique Number to the ID of the input fields
//For Loop that helps to total up the quantities being selected in each picker
total=0;
for (i = 0; i<Picker; i++) {
total= total + $('#AddLocQtyPick'+i).val() * 1.0;
}
QtyReqTot= QtyReq - total; //Variable decides max value of pick on appends using previous selection
What gets appended:
//The Location/Quantity Picker that gets appended
var appendTxt = '<tr id="' + Picker + '"><td></td><td><select class= "selectbox" id="LocationPickerSelect'+ Picker +'"><option value="0">Please select a location'+loc+'</option></select></td><td><input class= "QtyPicker" id="AddLocQtyPick'+ Picker +'" type="number" min="1" max='+QtyReqTot+' value="1" onkeydown="return false"></td></tr>';
I didn't know if I could use the same sort of technique in using For Loops to use with the incrementing IDS that the Location Picker has, like I did with the Quantity slider as I've seen some examples that suggest this whilst others have said to never use loops in this situation.
My main issue boils down to how I can select an option in one unique menu and remove that option from another unique menu that has the same options.
I'll thank you now for any input/advice received and for patience in my abilities!
EDIT: Problem Solved
The problem I was having did involve trying to take the unique ID's into consideration when writing my syntax. Confirmation for the use of a for loop allowed me to compare with my previous loop I created when totalling the picker quantities.
//For Loop that removes previously selected locations from the append
for (i = 0; i<Picker; i++) {
LocSelect= $('#LocationPickerSelect'+i).val();
$('#LocationPickerSelect'+Picker+' option[value="'+LocSelect+'"]').remove();
}
I will suggest to go with following approach:
Instead of simply adding all the <option> to each select box like below:
$.each(data.Locations, function(i, value) {loc +='<option value="'+ value.Location + '">' + value.Location + ' -- Qty: ' +value.Qty +'</option>';
})
Go for following code which check; which all <option> are already been selected by end user. And adds only those which are unused previously.
var prevSelectedLoc = [];
if(Picker > 0)
{
for(i=0;i<Picker;i++)
{
prevSelectedLoc.push($("select#LocationPickerSelect"+i).val());
}
}
$.each(data.Locations, function(i, value) {
if($.inArray(value.Location,prevSelectedLoc) == -1)
{
//if current option has not been previously selected then only add it to current select box
loc +='<option value="'+ value.Location + '">' + value.Location + ' -- Qty: ' +value.Qty +'</option>';
}
});
The problem I was having did involve trying to take the unique ID's into consideration when writing my syntax. Confirmation for the use of a for loop allowed me to compare with my previous loop I created when totalling the picker quantities.
//For Loop that removes previously selected locations from the append
for (i = 0; i<Picker; i++) {
LocSelect= $('#LocationPickerSelect'+i).val();
$('#LocationPickerSelect'+Picker+' option[value="'+LocSelect+'"]').remove();
}
I'm working with Zend Framework 1.12 and I've need to be able to dynamically add and delete fields from a sub-form, in this case we're associating hyperlinks to a parent "promotion".
I haven't found a way to accomplish dynamically adding and removing elements via Zend, and the rare tutorial I've found that claimed to do this are half a decade old and aren't working when I attempt them.
So what I am doing is storing the links I need to work with in a Zend Hidden input field and then dealing with the JSON data after I submit. Not very efficient, but it's the only thing I've gotten to work so far.
Below is the section of the code I'm working with:
Assume a form like:
<form action="/promos/edit/promo_id/15" method="POST" id="form_edit">
<!-- input is Zend_Form_Element_Hidden -->
<input type="hidden" id="link_array" value="{ contains the JSON string }"/>
<button id="add_link">Add Link</button>
</form>
The purpose is that every time the Add Link button is pressed, the form adds fields to allow the user to input new hyperlinks that will be associated with the specific items.
Here's the function:
// add links
$('#add_link').click(
function(e) {
e.preventDefault();
link = '<div class="p_link new_link">' +
'<div class="element_wrap">' +
'<label for="link_name" class="form_label optional">Text: </label>' +
'<input type="text" id="new_link_name" name="link_name"/>' +
'</div>' +
'<div class="element_wrap">' +
'<label for="link_http" class="form_label optional">http://</label>' +
'<input type="text" id="new_link_http" name="link_http"/>' +
'</div>' +
'<div class="element_wrap">' +
'<button class="submit delete_link">Delete</button>' +
'</div>' +
'</div>';
$('#add_link').prev().after(link);
}
);
Now, what I need to do is on submit, for every new_link class element, to take the links name and http reference and place it in a json object. Here's the code as I have it so far (I know I don't have both input fields represented at this point):
$('#submit').click(
function(e) {
e.preventDefault();
var link_array = [];
var new_links = document.getElementsByClassName('new_link');
$.each(new_links, function() {
console.log(this);
var n = $(this).children('#new_link_name').text();
console.log(n);
link_array.push({'link_name':n}); //'link_http':h
});
console.log(JSON.stringify(link_array));
}
);
My problem is that: var new_links = document.getElementsByClassName('new_link'); will collect all the newly added new_link elements, but it does not pull in any value that has been input into the text fields.
I need to know how I can apparently bind any input I make to the input field's value attribute, because right now anything I type into these new elements are tossed out and the field appears empty when it's anything but.
$('#submit').click(
function(e) {
e.preventDefault();
var link_array = [];
var new_links = $('.new_link');
$.each(new_links, function() {
console.log(this);
var n = $(this).find('input').val(); // you need input values! This line //is changed...
console.log(n);
link_array.push({'link_name':n}); //'link_http':h
});
console.log(JSON.stringify(link_array));
}
);
JSFIDDLE: http://jsfiddle.net/DZuLJ/
EDit: You can't have multiple IDS (make class for each input, and target class, if you want link names and http's)
I created a div and a button. when the button clicked, there will be a group of element(included 1 select box and 2 text inputs) inserted into the div. User can add as many group as they can, when they finished type in data of all the group they added, he can hit save button, which will take the value from each group one by one into the JSON object array. But I am stuck in the part how to get the value from each group, so please help, thank you.
The code for the div and the add group button function -- AddExtra() are listed below:
<div id="roomextra">
</div>
function AddExtra() {
$('#roomextra').append('<div class=extra>' +
'<select id="isInset">' +
'<option value="Inset">Inset</option>' +
'<option value="Offset">OffSet</option>' +
'</select>' +
'Length(m): <input type="text" id="insetLength">' +
'Width(m): <input type="text" id="insetWidth">' +
'Height(m): <input type="text" id="insetHeight">' +
'</div>');
}
function GetInsetOffSetArray (callBack) {
var roomIFSDetail = [{
"IsInset": '' ,
"Length": '' ,
"Width": '' ,
"Height": ''
}];
//should get all the value from each group element and write into the array.
callBack(roomIFSDetail);
}
This should just about do it. However, if you're dynamically creating these groups, you'll need to use something other than id. You may want to add a class to them or a data-* attribute. I used a class, in this case. Add those classes to your controls so we know which is which.
var roomIFSDetail = [];
var obj;
// grab all of the divs (groups) and look for my controls in them
$(.extra).each(function(){
// create object out of select and inputs values
// the 'this' in the selector is the context. It basically says to use the object
// from the .each loop to search in.
obj = {
IsInset: $('.isInset', this).find(':selected').val() ,
Length: $('.insetLength', this).val() ,
Width: $('.insetWidth', this).val() ,
Height: $('.insetHeight', this).val()
};
// add object to array of objects
roomIFSDetail.push(obj);
});
you'd better not to use id attribute to identity the select and input, name attribute instead. for example
$('#roomextra').append('<div class=extra>' +
'<select name="isInset">' +
'<option value="Inset">Inset</option>' +
'<option value="Offset">OffSet</option>' +
'</select>' +
'Length(m): <input type="text" name="insetLength">' +
'Width(m): <input type="text" name="insetWidth">' +
'Height(m): <input type="text" name="insetHeight">' +
'</div>');
}
and then, usr foreach to iterate
$(".extra").each(function() {
var $this = $(this);
var isInset = $this.find("select[name='isInset']").val();
var insetLength = $this.find("input[name='insetLength']").val();
// ... and go on
});
A common problem. A couple things:
You can't use IDs in the section you're going to be repeating, because IDs in the DOM are supposed to be unique.
I prefer to use markup where I'm writing a lot of it, and modify it in code rather than generate it there.
http://jsfiddle.net/b9chris/PZ8sf/
HTML:
<div id=form>
... non-repeating elements go here...
<div id=roomextra>
<div class=extra>
<select name=isInset>
<option>Inset</option>
<option>OffSet</option>
</select>
Length(m): <input id=insetLength>
Width(m): <input id=insetWidth>
Height(m): <input id=insetHeight>
</div>
</div>
</div>
JS:
(function() {
// Get the template
var container = $('#roomextra');
var T = $('div.extra', container);
$('#addGroup').click(function() {
container.append(T.clone());
});
$('#submit').click(function() {
var d = {};
// Fill d with data from the rest of the form
d.groups = $.map($('div.extra', container), function(tag) {
var g = {};
$.each(['isInset', 'insetLength', 'insetWidth', 'insetHeight'], function(i, name) {
g[name] = $('[name=' + name + ']', tag).val();
});
return g;
});
// Inspect the data to ensure it's what you wanted
debugger;
});
})();
So the template that keeps repeating is written in plain old HTML rather than a bunch of JS strings appended to each other. Using name attributes instead of ids keeps with the way these elements typically work without violating any DOM constraints.
You might notice I didn't quote my attributes, took the value attributes out of the options, and took the type attributes out of the inputs, to keep the code a bit DRYer. HTML5 specs don't require quoting your attributes, the option tag's value is whatever the text is if you don't specify a value attribute explicitly, and input tags default to type=text if none is specified, all of which adds up to a quicker read and slimmer HTML.
Use $(".extra").each(function() {
//Pull info out of ctrls here
});
That will iterate through all of your extra divs and allow you to add all values to an array.