jQuery Cloned django-selectable Autocomplete Dropdowns Not Working - javascript

As the title states, I have a django-selectable autocomplete form field on my page, that I am trying to clone dynamically after page load. The cloning part works, but the autocomplete fields do not function. I don't know the internals of django-selectable, and I'm still learning jQuery so I am lost as far as figuring out how to "fix" the autoselect functionality.
My general approach is this: I render the form widget using django template variable inside a div container, and I clone the div container.
HTML
<div class="autocomplete" id="autocomplete_{{ form.instance.id}}">{{form.autocomplete_dropdown}}</div>
jQuery
// This works, just the cloned form lacks "autocomplete" functionality.
var autocompleteArray = theDiv.find('.autocomplete');
var acClone = autocompleteArray.clone();
table.find(".column").append(acClone);
Based on SunnySydeUp's comments I made the following revisions:
jQuery
// Clone the div and all its contents
var acClone = autocompleteArray.clone(true, true);
// Get the children of the div
var acCloneChildrenArray = acClone.children();
// iterate through the children array, modify ids where they exist to make them unique
// e.g., unique id contained in idSuffix.
for (var i = 0; i < acCloneChildrenArray.length; i++) {
// if it has an id, make it unique
if (acCloneChildrenArray[i].getAttribute('id')) {
var ident = acCloneChildrenArray[i].getAttribute('id')
acCloneChildrenArray[i].setAttribute('id', ident+'_'+idSuffix);
};
};
Now the data and events are copied, but they are tied to the prototype/master dropdown. That is, clicking one of the cloned objects actually triggers the dropdown for the master. I guess the question comes down to how to attach the event handler dynamically to the new dropdowns?
Final working code (has a minor bug--duplicated dropdown button, but the autocomplete and dropdown functionality works, per SunnySydeUp's solution).
jQuery
// Clone the div
// We leave clone deepcopy flags at default==false
var acClone = autocompleteArray.clone();
// Get the children of the div
// You don't need to set unique id's on the children, it's irrelevant.
// Bind the new selectable fields to the event handlers.
window.bindSelectables('body');

I haven't used django-selectable before but I'm guessing it uses javascript/jQuery to make the autocomplete work. When you call clone, it doesn't clone the javascript for the dropdown. Try doing:
var acClone = autocompleteArray.clone(true);
Passing in true will make jQuery also copy the data and events on that input.
Clone documentation

Related

JQUERY DOM: Select Elements Created After Dom Load

I am working on a project where I need to change the value of all select inputs of a certain class when a function is called. The problem is some of the select inputs do not exist when the dom is first loaded, they are created dynamically via Javascript.
The function works fine for selecting all the select inputs that exist when the page was loaded, but does not work for any select inputs that were added to the dom dynamically.
I understand event binding with .on but in this particular case I am not trying to key off of an event like click. I want to get all elements of this class when this function is called.
Here is the code I am using to create the new select elements.
var this_cell = document.getElementById('produce_batch_line_td['+x+']');
var new_select = document.createElement("select");
new_select.name = "produce_batch_line["+x+"]";
new_select.id = "produce_batch_line["+x+"]";
new_select.className = "produce_batch_line["+invoice_number+"]";
this_cell.appendChild(new_select);
var new_option = document.createElement("option");
new_option.text = "test";
new_option.value = "test";
new_select.add(new_option);
Here is the code I am using to select all select elements of this class.
function SetDetailValue(invoice_number, obj) {
$(".produce_batch_line\\["+invoice_number+"\\]").each(function() {
this.value = obj.value;
});
}
How can I get items of this class added to the dom dynamically?
Check this link. I have put one that already exist. And when you click add button it creates dynamicly as well. When you Click the set button it finds them with a java query and puts them into a for loop that changes each ones value one by one.
http://cr8code.co/editor.php?workid=1a446530189d751d0b15ce104a286eee
Here is the DEMO

Bug when trying to update an HTML table value in the DOM

I am trying to implement a simple update functionality for the values in my table. I have an edit button, which triggers a modal where I edit the values and save them. In order the values to be immediately update in the DOM I am using the following jquery code on save:
$('#lblEditDeleteProducts').find("tr .nameDom").text("new val");
$('#lblEditDeleteProducts').find("tr .brandDom").text("new val");
$('#lblEditDeleteProducts').find("tr .priceDom").text("new val");
The problem is that with this code intead of one row in my table all the rows get updated with the "new value". I am very new to jquery and I am out of ideas how to solve this, so any help will be appreciated.
Here is my table structure :
As there is not much information of your HTML code
var selectedTR;
$("#lblEditDeleteProducts tr").click(function(){
selectedTR=$(this);
//init your modal pop up here or do it globally
})
Let assume the ID of save button is #save
$("#save").click(function(){
selectedTR.find(".nameDom").text("new val"); // get relative value from the mdoal input
selectedTR.find(".brandDom").text("new val");
selectedTR.find(".priceDom").text("new val");
})
If you are interested you can use this plugin also (advanced feature) datatable inline edit
The selectors that find is using are too general, so they're selecting all matching rows.
$('#lblEditDeleteProducts').find("tr .nameDom").text("new val");
Here's what jQuery is doing with that particular line of code (the same thing applies to all the others, too):
Get lblEditDeleteProducts by ID
Using that node, find() all descendant elements that match the selector tr .nameDom
Update the text of all nodes that it finds.
In your case, that selector matches every element in every row because they're all descendants of #lblEditDeleteProducts; there's no way to filter out just those you want with the code that you've written.
You'll need a way of explicitly determining which row to update.
Based on your comment that the edit button is in the each row, you can reference the corresponding row with closest
$("EDIT BUTTON SELECTOR").click(function(){
var $btn = $(this);
var $row = $btn.closest("tr");
$("DIALOG SELECTOR").dialog({
buttons:{
Save: function(){
//bunch of stuff
$row.find("td.nameDom").text("new val");
}
}
});
});

Kendo toolbar append is not working

I am trying to append my Kendo Grid toolbar after some functions using following::
1) I am getting the toolbar as::
var toolbar = $("#Grid").find(".k-grid-toolbar").html();
2) then after some changes to Grid using grid.setOptions(JSON.parse(options)) which causes disappear of Toolbar i am again appending toolbar to grid as::
$("#Grid").find(".k-grid-toolbar").html(toolbar);
Here toolbar is appended properly but I am not able to use those functions(i.e. Dropdown inside of toolbar).
How can i get my toolbar Dropdown working?
Thanks in advance
Getting the html() method provides ONLY the HTML code, and not the JavaScript attached to the elements from this HTML. So when you inject your HTML code in the toolbar, you need to call again the JavaScript attached to the elements. If you want to get a kendo widget configuration, for example a dropdownList, you need to call options and dataSource from your widget.
E.g:
var $toolbar = $("#Grid").find(".k-grid-toolbar"),
toolbar = $toolbar.html(),
// Dropdown list Element
$ele = $("input[name=myInput]", $toolbar.get(0)),
// Dropdown list Widget object
ddl = $ele.data("kendoDropDownList"),
cfg = ddl.options;
// toJSON returns objects without the observer properties
cfg.dataSource = ddl.dataSource.data().toJSON();
// HERE YOU REBUILD YOUR TABLE
$toolbar.html(toolbar);
$("input[name=myInput]", $toolbar.get(0)).kendoDropDownList(cfg);
If the elements you add to the toolbar are always the same, I would suggest you create instead a function with the grid as argument (and the data, if the data changes):
function setToolbarContent(grid){
var $toolbar = grid.find(".k-grid-toolbar");
$toolbar.html('My HTML String');
$toolbar.find("input[name=myInput]").kendoDropDownList({my: 'cfg'});
}
And by the way, if you were adding the toolbar config and template to grid.setOptions(), maybe it wouldn't disappear in the first place :)

create a new drop down based on another drop down in javascript

Here is my requirement.
List item
I have a couple of dropdowns A and B
I have a javascript key-value variable created:
var keyvalue={"key1":["value1","value2"],"key2":["value2","value4"]}
I am populating the keys in dropdown A, on selecting this dropdown, i am populating the corresponding values (froom the keyvalue variable) into the drop down B
Here is the sample code i a using :
The problem is even if i select a different option in dropdown A, the corresponding old option is present in the new drop down,i.e, new values are appended, rather than creating a new drop down
Any help is appreciated,thanks in advance.
You need to remove all options before populating. Add this directly right after your var quantity statement.
while (selectvalue.options.length > 0) {
selectvalue.remove();
}
Also, as mentioned by #francisco-presencia, you should lose the onchange in the HTML and instead use an event listener within your script.
I recommend you go the separation of concerns route. That means deleting the onclick="" event, and instead doing:
$('#key').change(function(){
$('#value').remove();
// Do the rest of the logic of retrievevalue() here.
});
You should use empty() to remove the old options before appending the new.
You can see it on my sample Fiddle:
JS Fiddle Here
$('#select2').empty().append(Weapons);

How to get values from dynamically added (using javascript) elements?

On my aspx page I dynamically create html controls on client side using javascript. For example, after page load you can click button in a browser, by clicking button html input and select elements appear. You may click once again, and this elements (input and select) will added again. So, you can create so many inputs and selects as you want (all this using javascript, no postbacks)
After user created some inputs and selects and entered some information in it, he posted form. I want on server side to find all this dynamically added elements and perform some actions depends on values in this controls.
How can I find dynamically added elements, and what is the best and elegant way to achieve this?
Thanks in advance.
In the Javascript that creates the new elements, increment a counter each time an element is created. Add the value of the counter to the name of the input element so each element has a unique name.
Add the final value of the counter to a hidden form field when the form is posted.
In your server side code, create a loop that starts at zero and continues until you have reached the value of the counter. Within the loop, fetch the posted value of the corresponding form field.
When you add the elements, assign unique IDs to them, and then retrieve their values using Request.Form["UniqueIdHere"] (C#) or Request.Form("UniqueIdHere") (VB.NET).
Create a loop that loops through each input and select object, that grabs the name/id of the current object and its corresponding value. Then add those items to an array and once the loop is completed, pass those values to your aspx file.
You can view an example with this approach at: http://jsfiddle.net/euHeX/. It currently just alerts the values, but you could easily modify it to pass the values as a parameter via ajax to your handler aspx file. The code will add new inputs or select boxes based off of the input provided. This would of course be modified to reflect your current setup.
HTML:
<div id="dynamic"></div>
<input type="button" id="submit-form" value="Submit>>">
JavaScript (using jQuery):
function createInput(type){
for(var i=0; i<5; i++){
if(type==0){
var obj = '<input type="text" id="'+i+'" class="dynamicContent">';
}else if(type==1){
var obj = '<select id="'+i+'" class="dynamicContent"><option>--Select--</option></select>';
}
$("#dynamic").append(obj);
}
}
function getContent(){
var inputArray = [];
$(".dynamicContent").each(function(k,v){
var o = $(this);
var oType;
if(o.is("input")){ oType = "input"; }
if(o.is("select")){ oType = "select"; }
var oID = oType+o.attr("id");
var oValue = o.val();
inputArray.push(oID+'='+oValue);
});
alert(inputArray);
}
$("#submit-form").click(function(){
getContent();
});
// Set type to 0 for input or 1 for select
var type = '1';
createInput(type);
If you're using jQuery you can use .live() to achive this like a peace of cake!
http://api.jquery.com/live/
I don't know if your controls will survive the postback the way you're creating them, but a good technique for accessing dynamically generated controls (assuming that you've figured out how to persist them) is to do something like the following:
Add a panel to your page. Add your dynamically created controls to this panel.
In the OnClick event handler (or other method), do something like the following:
foreach (DropDownList ddl in Panel1.Controls.OfType<DropDownList>())
{
//put code here
}
foreach (TextBox txt in Panel1.Controls.OfType<TextBox>())
{
//put code here
}

Categories

Resources