I'm rendering form on a page with help ng-repeat, data for this form comes dynamically from request. In this data I have nested array - categories. Inside of this array defined ids and list of this ids I can see in my form. From another request I get another array where defined names for ids. How can I assign key value from one variable to key value from another variable that display on the page list of names instead of list of ids
This is plunker with my problem. I appreciate any help, thanks in advance.
html of my form
<form style="padding: 15px" ng-submit="submitForm(rowData)">
<div class="form-group row">
<div ng-repeat="(key, value) in rowData">
<div ng-if="key | id">
<label class="col-sm-6">{{key | makeUppercase}}</label>
<div class=" col-sm-6">
<input class="form-control rowValue"
id="rowData[key]"
ng-if="!isObject(value)"
type="text"
ng-model="rowData[key]"
/>
<span
class="form-control rowValue"
id="categories"
ng-if="isObject(value) && key == 'categories'"
ng-model="rowData.categories">
{{rowData.categories}}
</span>
</div>
</div>
</div>
</div>
<div class="pull-right">
<button type="submit" class="btn btn-default"
ng-if="rowData">Save</button>
<button type="button" class="btn btn-default" ng-if="rowData"
ng-click="cancelForm()">Cancel</button>
</div>
</form>
My implementation is very naive but it displays what you want.
I add this function to your controller
$scope.getCategoryIns = function(ids){
var categoriesName = [];
for (var j = 0; j < ids.length; j ++){
id = ids[j];
for(var i= 0; i < $scope.categories.length;i++)
{
if ( $scope.categories[i].id == id){
categoriesName.push($scope.categories[i].name);
}
}
}
var str = categoriesName.join(', ');
return str;
}
and in HTML use this function as following
<span class="form-control rowValue" id="categories" ng-if="isObject(value) && key == 'categories'" ng-model="rowData.categories">
{{getCategoryIns(rowData.categories)}}</span>
plnkr here
You could create a new method in your controller that maps the numbers in $scope.rowData.categories to $scope.categories.id and returns values of the corresponding category names:
$scope.getCategoryName = function (categoriesArr) {
return categoriesArr.map(function(curr) {
return $scope.categories.filter(function(el){
return el.id === curr; //filter out the appropriate category by id
})[0].name; //select the item and grab its name property
})
}
and update your HTML to use the new method:
<span>
class="form-control rowValue"
id="categories"
ng-if="isObject(value) && key == 'categories'"
ng-model="rowData.categories">
{{getCategoryName(rowData.categories)}}
</span>
Related
I passed an array of production locations from the controller to the edit.blade.php view. In this edit file there is a Select Option field with three entries.
In the edit.blade.php I also have a box with different products (from a products array) displayed in rows. These products can be clicked individually. After clicking on a product, I would like to compare the already entered value for production location from the product array with the already generated select option field. If they match, the field in the production locations array should be changed as selected.
All via Javascript without POST or Ajax since the data is on the page ready to be accessed.
Here is the current Code(HTML/BLADE/Javascript):
// part of the fields which will be filled
<div class="form-group row">
<label for="" class="col-sm-2 col-form-label">Produktionsort</label>
<div class="col-sm-2">
<select class="form-control m-bot15" id="Produktionsort" name="Produktionsort" data-placeholder="dadada">
<option id="">----</option>
#foreach ( $data['produktionsort'] as $produkteOrt )
<option value="{{$produkteOrt->Ort}}" id="{{$produkteOrt->Ort}}"> {{$produkteOrt->Ort}}</option>
#endForeach
</select>
</div>
<div class="col-sm-2">
</div>
<label class="col-sm-2 col-form-label">Produktart</label>
<div class="col-sm-4">
<select class="form-control" id="Produktart" name="Produktart">
<option id="Produktart">----</option>
#foreach ( $data['produktart'] as $produkteArt )
<option value="{{$produkteArt->prodartBezeichnung}}" id="Produktart"> {{$produkteArt->prodartBezeichnung}}</option>
#endForeach
</select>
</div>
</div>
// current javascript
var jqueryarray; var dasProdukt; var currentElementID; var elementArr = document.getElementsByClassName("flexRadioDefault"); //alert(elementArr.length); for (let i = 0; i < elementArr.length; i++) { const element = elementArr[i]; element.addEventListener('click', function()
{
element.parentElement.parentElement.style.backgroundColor = 'lightgrey';
for (let j = 0; j < elementArr.length; j++)
{
const e = elementArr[j];
if (element !== e)
{
e.parentElement.parentElement.style.backgroundColor = '#ebeef0';
}
}
<?php
if ( isset($data['produktarray']))
{
?> jqueryarray = <?php echo (json_encode($data['produktarray']));
}
?>;
document.getElementById('Menge').value = jqueryarray[currentElementID]['prodDatMenge'];
document.getElementById('anzahlPfosten').value = jqueryarray[currentElementID]['prodDatAnzahlPfosten'];
document.getElementById('Vermerk').value = jqueryarray[currentElementID]['prodDatVermerk'];
document.getElementById('Restarbeiten').value = jqueryarray[currentElementID]['prodDatRestarbeiten'];
alert(jqueryarray[currentElementID]['prodDatProduktionsOrt'] );
enter image description here
I have created a form which can be dynamically changed using the buttons included. These buttons allow for more input fields to be added/removed. The issue is that the input fields created are not posting any data/ Values in those fields not being added to the $POST array on the submit of the form.
The main functions below resposible for adding and removing rows is RemoveRows() and addRows()
What should happen is that on submit all values in the form should be "posted" then I can access all of those fields via $_POST["nameOfField"].
The way I have currently approached this is to create an input fields with the relevant id's and names then append that field to where the "hard coded" fields exists.
From my initial debugging none of the fields that have been added via javascript are in $Post which I have checked via var_dump($_REQUEST);
I have also seen that the nodes that are added are not elements of the form tag even though the nodes are added between the opening and closing tag. This can be seen in the doBeforeSubmit() Function where we can see all elements that are children of the and this never changes as rows are added/removed.
function showPlatforms() {
let nacellesOptions = ["Option1", "option2", "Option3"];
let milOptions = ["Option1", "option2", "Option3"]
let highOptions = ["Option1", "option2", "Option3"]
let entry = document.getElementById("vs")
let platfom = document.getElementById("platform")
if (platform.hasChildNodes()) {
var lastChild = platfom.lastElementChild
while (lastChild) {
platfom.removeChild(lastChild)
lastChild = platform.lastElementChild
}
}
if (entry.value == "Nacelles") {
for (var i = 0; i < 2; i++) {
var option = document.createElement("option");
option.value = nacellesOptions[i]
option.innerHTML = nacellesOptions[i]
platform.appendChild(option)
}
} else if (entry.value == "Military") {
for (var i = 0; i < 2; i++) {
var option = document.createElement("option");
option.value = milOptions[i]
option.innerHTML = milOptions[i]
platform.appendChild(option)
}
} else {
for (var i = 0; i < 2; i++) {
var option = document.createElement("option");
option.value = highOptions[i]
option.innerHTML = highOptions[i]
platform.appendChild(option)
}
}
}
function formOptions() {
let entry = document.getElementById("type")
if (entry.value == "Engineering MAM") {
document.getElementById("WBS").disabled = false
document.getElementById("Desc").disabled = false
document.getElementById("ProName").disabled = false
} else {
document.getElementById("WBS").disabled = true
document.getElementById("Desc").disabled = true
document.getElementById("ProName").disabled = true
}
}
function formoptions2() {
let entry2 = document.getElementById("organisation")
if (entry2.value == "Aftermarket") {
document.getElementById("COT").disabled = false
document.getElementById("COC").disabled = false
} else {
document.getElementById("COT").disabled = true
document.getElementById("COC").disabled = true
}
}
count = document.getElementById("partNum").childElementCount
function addRows() {
rowNames = ["partNum", "partDesc", "leadTime", "quantity", "dateReq", "unitCost", "unitExtention", "unitSaleValue", "estSalesValue"]
rowNames.forEach(addRow, count)
count = document.getElementById("partNum").childElementCount
//doBeforeSubmit()
}
function doBeforeSubmit() {
var es = document.getElementById("form").elements;
var l = es.length;
var msgs = [];
for (var idx = 0; idx < l; idx++) {
var e = es[idx];
msgs.push('name=' + e.name + ', type=' + e.type + ', value=' + e.value);
}
alert(msgs.join('\n'));
return false;
}
function addRow(id) {
let col = document.getElementById(id)
var box = document.createElement("INPUT")
box.setAttribute("type", "text")
box.setAttribute("id", id + count)
box.setAttribute("name", id + count)
box.setAttribute("class", "form-control")
col.appendChild(box)
}
function RemoveRows() {
rowNames = ["partNum", "partDesc", "leadTime", "quantity", "dateReq", "unitCost", "unitExtention", "unitSaleValue", "estSalesValue"]
rowNames.forEach(removeBoxes)
count = document.getElementById("partNum").childElementCount
}
function removeBoxes(item) {
let box = document.getElementById(item)
let last = box.lastChild
box.removeChild(last)
}
function checkData() {
// if all stuff is correct do this:
document.getElementById("submit").disabled = false
// else dont activate the submit button.
}
<form method="post" id="form" action="SubmitMAM.php">
<div class="row" id="productRow" style="width:95%; margin:auto">
<div id="partNo" class="col-2">
<h3>Part Number:</h3>
</div>
<div class="col-2">
<h3>Part Description:</h3>
</div>
<div class="col-1">
<h3>Lead Time:</h3>
</div>
<div class="col-1">
<h3>Quantity:</h3>
</div>
<div class="col-1">
<h3>Date Required:</h3>
</div>
<div class="col-1">
<h3>Unit Cost:</h3>
</div>
<div class="col-2">
<h3>Unit Cost Extension:</h3>
</div>
<div class="col-1">
<h3>Unit Sale Value:</h3>
</div>
<div class="col-1">
<h3>Est Sales Value:</h3>
</div>
</div>
<div class="row" id="productRow" style="width:95%; margin:auto">
<div id="partNum" class="col-2">
<input type="text" id="partNum0" class="form-control" name="partNum0">
</div>
<div id="partDesc" class="col-2">
<input type="text" id="partDesc0" class="form-control" name="partDesc0">
</div>
<div id="leadTime" class="col-1">
<input type="text" id="leadTime0" class="form-control" name="leadTime0">
</div>
<div id="quantity" class="col-1">
<input type="text" id="quanitity0" class="form-control" name="quantity0">
</div>
<div id="dateReq" class="col-1">
<input type="text" id="dateReq0" class="form-control" name="dateReq0">
</div>
<div id="unitCost" class="col-1">
<input type="text" id="unitCost0" class="form-control" name="unitCost0">
</div>
<div id="unitExtention" class="col-2">
<input type="text" id="unitExtention0" class="form-control" name="unitExtention0">
</div>
<div id="unitSaleValue" class="col-1">
<input type="text" id="unitSaleValue0" class="form-control" name="unitSaleValue0">
</div>
<div id="estSalesValue" class="col-1">
<input type="text" id="estSalesValue0" class="form-control" name="estSalesValue0">
</div>
<button onclick="addRows()" class="btn btn-primary" type="button">Add a Product</button>
<button onclick="RemoveRows()" class="btn btn-primary" type="button">Remove Row</button>
<button onclick="checkData()" class="btn btn-primary" type="button">Check Data</button>
<br>
<button type="submit" name="submit" id="submit" class="btn btn-primary" disabled>Submit</button>
</form>
PHP:
<?php
var_dump($_REQUEST)
?>
UPDATE:
The code has been changed to use a php array by adding square brackets into the name which produces the following html:
<input type="text" id="partNum0" class="form-control" name="partNum[]">
<input type="text" id="partNum1" name="partNum[]" class="form-control">
<input type="text" id="partNum2" name="partNum[]" class="form-control">
You just need to use the name property of the input and add [] at the end, as GrumpyCrouton said. PHP parse it as an array, and you can access it as:
$partNum = $_POST["partNum"];
FIXED: It turns out the above code did not have any issues with the logic or the way it should work, in the source code in visual studio the indentation of some of the Divs was off causing the browser to have issues in rendering the form correctly hence why the added boxes were not included in the form and their values not POSTED.
As a heads up to anyone with maybe a similar issue, it pays to have your code neat.
I have a div as follows:
<div class="questionholder" id="question5" style="display:none">
<div>
<h5>Select all that apply</h5>
<input class="input5" type="checkbox" id="ID1elementColor" name="ID1element" value="color"><label for="ID1elementColor"><p class="radioChoice">Color</p></label>
<input class="input5" type="checkbox" id="ID1elementHeight" name="ID1element" value="height"><label for="ID1elementHeight"><p class="radioChoice">Height</p></label>
<input class="input5" type="checkbox" id="ID1elementWeight" name="ID1element" value="weight"><label for="ID1elementWeight"><p class="radioChoice">Weight</p></label>
</div>
</div>
<div class="holdButtons">
<a class="text2button" onclick="displayquestion(6);">Next</a>
</div>
The user is expected to select all the checkboxes that apply to his situation. Let's assume he selects all 3.
When he clicks "Next", the function displayquestion(); will fire.
function displayquestion(a) {
var Elements = '';
var b = a - 1;
Elements = document.querySelector("#question" + b + " input[name=ID1element]").value;
}
Basically, the function is meant to store all the checked values into var Elements, which is meant to be an array.
However, I'm only getting the value of the first selected answer instead of an array of all selected answers.
How do I grab all the selected answers into an array?
No jQuery please.
Use querySelectorAll to get an array-like NodeList instead of querySelector, and then you can use Array.from to transform that NodeList into an array containing only the .value of the selected inputs:
function displayquestion(a) {
const b = a - 1;
const elements = Array.from(
document.querySelectorAll('#question' + b + ' input:checked'),
input => input.value
);
console.log(elements);
}
<div class="questionholder" id="question5">
<div>
<h5>Select all that apply</h5>
<input class="input5" type="checkbox" id="ID1elementColor" name="ID1element" value="color"><label for="ID1elementColor"><p class="radioChoice">Color</p></label>
<input class="input5" type="checkbox" id="ID1elementHeight" name="ID1element" value="height"><label for="ID1elementHeight"><p class="radioChoice">Height</p></label>
<input class="input5" type="checkbox" id="ID1elementWeight" name="ID1element" value="weight"><label for="ID1elementWeight"><p class="radioChoice">Weight</p></label>
</div>
</div>
<div class="holdButtons">
<a class="text2button" onclick="displayquestion(6);">Next</a>
</div>
Here is the script that you can use for that:
I haven't changed anything in your HTML structure. Except I have removed the display: none; from the style attribute of the class questionholder.
<script>
function displayquestion(b) {
let checkboxList = document.querySelectorAll("#question" + b + " input:checked");
let obj = [];
if (checkboxList.length > 0) { //Code works only if some checbox is checked
checkboxList.forEach(function(item) {
obj.push(item.value); //Contains the value of all the selected checkboxes.
});
}
console.log(obj); //array list containing all the selected values
}
</script>
<div class="questionholder" id="question5" style="">
<div>
<h5>Select all that apply</h5>
<input class="input5" type="checkbox" id="ID1elementColor" name="ID1element" value="color"><label for="ID1elementColor"><p class="radioChoice">Color</p></label>
<input class="input5" type="checkbox" id="ID1elementHeight" name="ID1element" value="height"><label for="ID1elementHeight"><p class="radioChoice">Height</p></label>
<input class="input5" type="checkbox" id="ID1elementWeight" name="ID1element" value="weight"><label for="ID1elementWeight"><p class="radioChoice">Weight</p></label>
</div>
</div>
<div class="holdButtons">
<a class="text2button" onclick="displayquestion(5);">Next</a>
</div>
Here is a JSFiddle link for that.
I hope this is helpful.
So first of I would make a variable for your
<a class="text2button">Next</a>. And I have removed the
onclick="displayquestion(6)" from your html.
Here is the variable.
var text2button = document.getElementsByClassName("text2button")[0];
text2button.addEventListener("click", displayquestion);
Here we have the function, so what I've done is.
I have created a variable var elements = []; Which is a empty array.
Then I create this variable var inputs = document.getElementsByClassName("input5");
This variable gets all the inputs with class input5.
Next I would loop through each of the inputs from the var inputs. Like this.
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].checked) {
elements.push(inputs[i].value);
}
}
So what I do here is loop through each input for (var i = 0; i < inputs.length; i++) and then I check if any of the inputs are checked if (inputs[i].checked), then I push them to the array var elements with elements.push(inputs[i].value);.
And then I use console.log(elements); so show it in the console.
Check out the snippet below to see it in effect.
Hope this helps.
var text2button = document.getElementsByClassName("text2button")[0];
text2button.addEventListener("click", displayquestion);
function displayquestion() {
var elements = [];
var inputs = document.getElementsByClassName("input5");
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].checked) {
elements.push(inputs[i].value);
}
}
console.log(elements);
}
<div class="questionholder" id="question5">
<div>
<h5>Select all that apply</h5>
<input class="input5" type="checkbox" id="ID1elementColor" name="ID1element" value="color"><label for="ID1elementColor"><p class="radioChoice">Color</p></label>
<input class="input5" type="checkbox" id="ID1elementHeight" name="ID1element" value="height"><label for="ID1elementHeight"><p class="radioChoice">Height</p></label>
<input class="input5" type="checkbox" id="ID1elementWeight" name="ID1element" value="weight"><label for="ID1elementWeight"><p class="radioChoice">Weight</p></label>
</div>
</div>
<div class="holdButtons">
<a class="text2button">Next</a>
</div>
I have a html form, where user need to enter the name and address of their office. The number of offices are dynamic.
I want to add an Add More button, so that users can enter the details of any number of offices.
My question is, how can I create an array of inputs where new elements can be added and removed using JavaScript. Currently, I'm doing it using js clone method, but I want an array, so that input data can easily be validated and stored to database using Laravel.
What I'm currently doing..
This is my HTML form where users have to enter the address of their clinic or office. I've taken a hidden input field and increasing the value of that field whenever a new clinic is added, so that I can use loop for storing data.
<div class="inputs">
<label><strong>Address</strong></label>
<input type="text" class="hidden" value="1" id="clinicCount" />
<div id="addresscontainer">
<div id="address">
<div class="row" style="margin-top:15px">
<div class="col-md-6">
<label><strong>Clinic 1</strong></label>
</div>
<div class="col-md-6">
<button id="deleteclinic" type="button" class="close deleteclinic"
onclick="removeClinic(this)">×</button>
</div>
</div>
<textarea name="address1" placeholder="Enter Clinic Address" class="form-control"></textarea>
<label class="text-muted" style="margin-top:10px">Coordinates (Click on map to get coordinates)</label>
<div class="row">
<div class="col-md-6">
<input class="form-control" id="latitude" type="text" name="latitude1" placeholder="Latitude" />
</div>
<div class="col-md-6">
<input class="form-control" id="longitude" type="text" name="longitude1" placeholder="Longitude" />
</div>
</div>
</div>
</div>
</div>
<div class="text-right">
<button class="btn btn-success" id="addclinic">Add More</button>
</div>
And my js code..
function numberClinic(){
//alert('test');
var i=0;
$('#addresscontainer > #address').each(function () {
i++;
$(this).find("strong").html("Clinic " + i);
$(this).find("textarea").attr('name','name'+i);
$(this).find("#latitude").attr('name','latitude'+i);
$(this).find("#longitude").attr('name','longitude'+i);
});
}
$("#addclinic").click(function(e){
e.preventDefault();
$("#addresscontainer").append($("#address").clone());
numberClinic();
$("#addresscontainer").find("div#address:last").find("input[name=latitude]").val('');
$("#addresscontainer").find("div#address:last").find("input[name=longitude]").val('');
$("#clinicCount").val(parseInt($("#clinicCount").val())+1);
});
function removeClinic(address){
if($("#clinicCount").val()>1){
$(address).parent('div').parent('div').parent('div').remove();
$("#clinicCount").val(parseInt($("#clinicCount").val())-1);
}
numberClinic();
}
This way, I think I can store the data to the database but can't validate the data. I'm using the laravel framework.
One way you could do this is by using the position of the input in the parent as the index in the array, then saving the value in the array every time each input is changed. Then you can just add and remove inputs.
Sample code:
var offices = document.getElementById('offices');
var output = document.getElementById('output');
var data = [];
var i = 0;
document.getElementById('add').addEventListener('click', function() {
var input = document.createElement('input');
input.setAttribute('type', 'text');
input.setAttribute('placeholder', 'Office');
var button = document.createElement('button');
var index = i++;
input.addEventListener('keyup', function() {
for (var i = 0; i < offices.children.length; i++) {
var child = offices.children[i];
if (child === input) {
break;
}
}
// i is now the index in the array
data[i] = input.value;
renderText();
});
offices.appendChild(input);
});
document.getElementById('remove').addEventListener('click', function() {
var children = offices.children;
if (children.length === data.length) {
data = data.splice(0, data.length - 1);
}
offices.removeChild(children[children.length - 1]);
renderText();
});
function renderText() {
output.innerHTML = data.join(', ');
}
JSFiddle: https://jsfiddle.net/94sns39b/2/
I have a block of form elements which I would like to clone and increment their ID's using jQuery clone method. I have tried a number of examples but a lot of them only clone a single field.
My block is structured as such:
<div id="clonedInput1" class="clonedInput">
<div>
<div>
<label for="txtCategory" class="">Learning category <span class="requiredField">*</span></label>
<select class="" name="txtCategory[]" id="category1">
<option value="">Please select</option>
</select>
</div>
<div>
<label for="txtSubCategory" class="">Sub-category <span class="requiredField">*</span></label>
<select class="" name="txtSubCategory[]" id="subcategory1">
<option value="">Please select category</option>
</select>
</div>
<div>
<label for="txtSubSubCategory">Sub-sub-category <span class="requiredField">*</span></label>
<select name="txtSubSubCategory[]" id="subsubcategory1">
<option value="">Please select sub-category</option>
</select>
</div>
</div>
Obviously elements are lined up a lot better but you get the idea.
I would like to keep the id structure i.e. category1, subcategory1 etc as I use these to dynamically display select options based on the parent selection so if its possible to have each cloned block like category1/category2/category3 etc that would be great.
HTML
<div id="clonedInput1" class="clonedInput">
<div>
<label for="txtCategory" class="">Learning category <span class="requiredField">*</span></label>
<select class="" name="txtCategory[]" id="category1">
<option value="">Please select</option>
</select>
</div>
<div>
<label for="txtSubCategory" class="">Sub-category <span class="requiredField">*</span></label>
<select class="" name="txtSubCategory[]" id="subcategory1">
<option value="">Please select category</option>
</select>
</div>
<div>
<label for="txtSubSubCategory">Sub-sub-category <span class="requiredField">*</span></label>
<select name="txtSubSubCategory[]" id="subsubcategory1">
<option value="">Please select sub-category</option>
</select>
</div>
<div class="actions">
<button class="clone">Clone</button>
<button class="remove">Remove</button>
</div>
</div>
JavaScript - Jquery v1.7 and earlier
var regex = /^(.+?)(\d+)$/i;
var cloneIndex = $(".clonedInput").length;
$("button.clone").live("click", function(){
$(this).parents(".clonedInput").clone()
.appendTo("body")
.attr("id", "clonedInput" + cloneIndex)
.find("*").each(function() {
var id = this.id || "";
var match = id.match(regex) || [];
if (match.length == 3) {
this.id = match[1] + (cloneIndex);
}
});
cloneIndex++;
});
There is only one silly part :) .attr("id", "clonedInput" + $(".clonedInput").length) but it works ;)
JAvascript - JQuery recent (supporting .on())
var regex = /^(.+?)(\d+)$/i;
var cloneIndex = $(".clonedInput").length;
function clone(){
$(this).parents(".clonedInput").clone()
.appendTo("body")
.attr("id", "clonedInput" + cloneIndex)
.find("*")
.each(function() {
var id = this.id || "";
var match = id.match(regex) || [];
if (match.length == 3) {
this.id = match[1] + (cloneIndex);
}
})
.on('click', 'button.clone', clone)
.on('click', 'button.remove', remove);
cloneIndex++;
}
function remove(){
$(this).parents(".clonedInput").remove();
}
$("button.clone").on("click", clone);
$("button.remove").on("click", remove);
working example here
Another option would be to use a recursive function:
// Accepts an element and a function
function childRecursive(element, func){
// Applies that function to the given element.
func(element);
var children = element.children();
if (children.length > 0) {
children.each(function (){
// Applies that function to all children recursively
childRecursive($(this), func);
});
}
}
Then you can make a function or three for setting the attributes and values of your yet-to-be-cloned form fields:
// Expects format to be xxx-#[-xxxx] (e.g. item-1 or item-1-name)
function getNewAttr(str, newNum){
// Split on -
var arr = str.split('-');
// Change the 1 to wherever the incremented value is in your id
arr[1] = newNum;
// Smash it back together and return
return arr.join('-');
}
// Written with Twitter Bootstrap form field structure in mind
// Checks for id, name, and for attributes.
function setCloneAttr(element, value){
// Check to see if the element has an id attribute
if (element.attr('id') !== undefined){
// If so, increment it
element.attr('id', getNewAttr(element.attr('id'),value));
} else { /*If for some reason you want to handle an else, here you go*/ }
// Do the same with name...
if(element.attr('name') !== undefined){
element.attr('name', getNewAttr(element.attr('name'),value));
} else {}
// And don't forget to show some love to your labels.
if (element.attr('for') !== undefined){
element.attr('for', getNewAttr(element.attr('for'),value));
} else {}
}
// Sets an element's value to ''
function clearCloneValues(element){
if (element.attr('value') !== undefined){
element.val('');
}
}
Then add some markup:
<div id="items">
<input type="hidden" id="itemCounter" name="itemCounter" value="0">
<div class="item">
<div class="control-group">
<label class="control-label" for="item-0-name">Item Name</label>
<div class="controls">
<input type="text" name="item-0-name" id="item-0-name" class="input-large">
</div>
</div><!-- .control-group-->
<div class="control-group">
<label for="item-0-description" class="control-label">Item Description</label>
<div class="controls">
<input type="text" name="item-0-description" id="item-0-description" class="input-large">
</div>
</div><!-- .control-group-->
</div><!-- .item -->
</div><!-- #items -->
<input type="button" value="Add Item" id="addItem">
And then all you need is some jQuery goodness to pull it all together:
$(document).ready(function(){
$('#addItem').click(function(){
//increment the value of our counter
$('#itemCounter').val(Number($('#allergyCounter').val()) + 1);
//clone the first .item element
var newItem = $('div.item').first().clone();
//recursively set our id, name, and for attributes properly
childRecursive(newItem,
// Remember, the recursive function expects to be able to pass in
// one parameter, the element.
function(e){
setCloneAttr(e, $('#itemCounter').val());
});
// Clear the values recursively
childRecursive(newItem,
function(e){
clearCloneValues(e);
}
);
// Finally, add the new div.item to the end
newItem.appendTo($('#items'));
});
});
Obviously, you don't necessarily need to use recursion to get everything if you know going in exactly what things you need to clone and change. However, these functions allow you to reuse them for any size of nested structure with as many fields as you want so long as they're all named with the right pattern.
There's a working jsFiddle here.
Clone the main element, strip the id number from it.
In the new element replace every instance of that id number in every element id you want incremented with the new id number.
Ok, here's a quicky code here.
Basically, this part is the most important:
(parseInt(/test(\d+)/.exec($(this).attr('id'))[1], 10)+1
It parses the current id (using RegEx to strip the number from the string) and increases it by 1. In your case instead of 'test', you should put 'clonedInput' and also not only increase the value of the main element id, but the three from the inside as well (category, subcategory and subsubcategory). This should be easy once you have the new id.
Hope this helps. :)
Add data attribute to the input to get the field name, increment the value with variable.
html :
<td>
<input type="text" data-origin="field" name="field" id="field" required="" >
<div role="button" onclick='InsertFormRow($(this).closest("tr"),"tableID","formID");' id="addrow"> + </div>
</td>
and put this javascript function
var rowNum = 1;
var InsertFormRow = function(row, ptable, form)
{
nextrow = $(row).clone(true).insertAfter(row).prev('#' + ptable + ' tbody>tr:last');
nextrow.attr("id", rowNum);
nextrow.find("input").each(function() {
this.name = $(this).data("origin") + "_" + rowNum;
this.id = $(this).data("origin") + "_" + rowNum;
});
rowNum++;
}