Dynamic HTML to represent an array using jQuery

It was not too precisely indicated what to call this question, but here is the problem I am having:

I need to be able to submit an array or linked list of data via an HTML form. Since this array can have a variable length, I have two options:

  • Use some form of delimiter (for example, comma-delimited items in a list)
  • Import multiple inputs (for an array element) dynamically generated when new elements are added.

I would like to continue the second option, although I felt that since there will be many such “arrays” in this particular project, I have to create a jQuery plugin so that I can more easily implement this function in future forms.

As I work on this, I also added functionality for several types of input, selected, selected multipliers (through a separator) and related inputs (for example, with two text inputs for “first name” and “last name” which should be presented as a pair)

I have a basic layout, as I think it should work:

(function($) { // Self-calling anonymous function to avoid namespace collisions or compatibility issues $.fn.dynamicList = function( options ) { // jQuery plugin definition /* Set up default options here */ defaults = { option1: "value1", option2: "value2" }; var options = $.extend( defaults, options ); /* Step 1. Add a jQuery-UI plus icon to the DOM */ /* Note: I have an option to specify where this icon should go in the DOM. It defaults right after the last input */ plus = $("<span>").addClass( 'jquery-ui-classes' ); this.last().after( plus ); /* Step 2. Add a table to the DOM for displaying added values */ /* Note: I have an option to specify where this table should go in the DOM. It defaults right after the plus icon */ plus.after( table ); /* Step 3. Add a handler for our plus button */ this.delegate( plus, 'click', function() { /* Read the inputs, add their values to the table, empty the inputs */ /* Also, the last column of the table contains a minus button */ /* This is where I THOUGHT my first issue was.... */ minus = $("<span>").addClass( 'jquery-ui-classes' ); table.append( row ).append( minus ); }); /* Step 4. Add a handler for our minus button */ /* Since the minus is created within the plus handler we can't use "minus" here */ /* Instead I use a class name to locate it */ this.delegate( '.jquery-ui-minus-class', 'click', function() { /* Remove the relevant row from the table */ $(this).parents('tr').remove(); }); /* Step 5. Add our submit handler */ this.parents('form').first().submit(function() { /* We want all of the data in the table to be submitted with the form */ /* Therefore we create an input per cell and name it accordingly */ /* The name is just the name of the original input plus "[]" to make it an array */ /* This is where I thought my second problem was */ }); return this; // Maintain chain-ability }; )(jQuery); 

This code is called on the inputs that you want to replace with a dynamic list. If you select multiple inputs, they will become a list of related data (for example, an example of the first and last name). An example of how to call this will be as follows:

 <html> <head> <!-- Include jQuery and my dynamic list library here --> <script> $('#fn,#ln').dynamicList(); </script> </head> <body> <form> <input id="fn" name="first_name" /> <input id="ln" name="last_name" /> </form> </body> </html> 

This will create a dynamic list where you can enter the first and last name, and then click the plus button (now on the right or under the name of the last name based on your CSS rules), and it will add a row to the table containing the first name in one column, the last name in the other and the minus button in the last. You can continue to enter names and press this plus button, and the table expands unlimitedly down. When submitting a form (using the submit button or any other method), the table cells must become inputs.

I thought the first problem I encountered was in the plus handler. Since I'm inside the function called by clicking the plus button, the keyword this now refers to the DOM plus element of the icon. I cannot capture the value of the inputs to add them to the table. One of the proposed solutions was to create a global variable, which is a copy of an object for which the dynamic list function was called like this:

  . . . /* Step 2. Add a table to the DOM for displaying added values */ /* Note: I have an option to specify where this table should go in the DOM. It defaults right after the plus icon */ plus.after( table ); var dynamicList = this; /* Step 3. Add a handler for our plus button */ this.delegate( plus, 'click', function() { /* Read the inputs, add their values to the table, empty the inputs */ /* Also, the last column of the table contains a minus button */ /* This is where I THOUGHT my first issue was.... */ for( i = 0; i < dynamicList.length; i++ ) { // dynamicList.get(i) will give us each input in order } minus = $("<span>").addClass( 'jquery-ui-classes' ); table.append( row ).append( minus ); }); . . . 

My concern is that if I create multiple dynamic lists, they will override each other. It's true? If so, how can I overcome this?

The second problem I ran into was similar. After submitting the form, I need to find the table to get the values ​​to submit AND find the inputs to get the names under which they should be submitted.

However, going around the code to try to fix it, I ran into a problem much earlier than expected.

 Uncaught TypeError: Object [object Object] has no method 'replace' jquery-1.6.2.min.js:16 f.each.f.fn.(anonymous function) jquery-1.6.2.min.js:17 f.fn.extend.delegate jquery-1.6.2.min.js:17 $.fn.dynamicList jquery.dynamicList.js:76 (anonymous function) test.php:16 f.extend._Deferred.e.resolveWith jquery-1.6.2.min.js:16 e.extend.ready jquery-1.6.2.min.js:16 c.addEventListener.B jquery-1.6.2.min.js:16 

Look at line 76 of my dynamic list, this is the following line:

 this.delegate( plus, 'click', function() { 

Can't I call .delegate() since "this" refers to multiple jQuery objects? Or can I not call .delegate() because "this" is not the parent of the plus sign? And as soon as this problem is solved, how to solve my other problems?

EDIT -

I changed the name and I found a solution to my problem on line 76. I am not sure exactly how .delegate() works, because I tried first:

 this.first().parent().delegate( plus, 'click', function() { 

and he was still upset. Then I realized that I could just use the .click() function (I kind of goofed)

 plus.click( function() { 

I used similar logic when creating the minus button for each row. I added minus.click() after creating the minus button and before inserting it into the DOM, eliminating the need to use .delegate() anywhere in the code.

I'm not sure how to get the values ​​from the input fields inside the plus handler, since the keyword “this” was overwritten at this moment to refer to the plus button, and not to my input fields.

+4
source share
1 answer

I changed the name and I found a solution to my problem on line 76. I am not sure how .delegate () works, because I tried first:

 this.first().parent().delegate( plus, 'click', function() { 

and he was still upset. Then I realized that instead I could use the .click () function (I kind of goofed)

 plus.click( function() { 

I used similar logic when creating the minus button for each row. I added the minus .click () after creating the minus button and before pasting it into the DOM, eliminating the need to use .delegate () anywhere in the code.

+1
source

Source: https://habr.com/ru/post/1394323/


All Articles