Milligran
Milligran

Reputation: 3161

How to rename element ids to conform to model sequence collection

C# MVC web application

I have a button that adds input fields dynamically to my web page on a form. I specifically give the dynamically added elements an id and name to conform to my Model so that they get passed back as an collection of like items to match a “Artists” collection property in my model.

So the input elements name and ids are for example

Artists[0].artist
Artists[1].artist
Artists[2].artist

In my model I have:

   public Collection<Artist> Artists { get; set; }

    public class Artist
    {
        public string artist { get; set; }
    }

And here is my script to add remove an element:

var artists = new Array();

var AddArtist = function (e) {
    artistname = $("#artistinput").val();
    artists.push($("#artistinput").val());
    var addDiv, artistVal;
    addDiv = $("#artist");
    artistVal = $("#artistinput").val();

    var input_append = $('<div />'),
     label = $('<input />', {
         style: 'background-color:#e0ffff',
         Value: artistVal,
         id: 'artists[' + (artists.length - 1) + '].artist',
         name: 'artists[' + (artists.length - 1) + '].artist',
         readonly: true
     }),
     image = $('<img />', {
         id: 'removeartist',
         src: '/Content/bootstrap/img/cross-button.png',
         on: {
             click: function () {
                 input_append.remove();
                 artists.splice(artists.length - 1, 1);
                 var test = (artists.length - 1);
                 alert(test);
             }
         }
     }
                     );

    addDiv.append(input_append.append(label, image));

};

I can add/remove the elements on the actual page. The problem is, if I remove an element from the middle or beginning, the sequence of the name ids are broken and when the collection get passed back to my model the Artists collection is now empty.

So instead of

Artists[0].artist
Artists[1].artist
Artists[2].artist

This may be passed back:

Artists[0].artist
Artists[2].artist

Which is no longer a collection based on how the view is mapped to the model.

I need to rename all the name/ids in a ordered sequence once an item has been removed.

What’s the easiest solution for this problem.

So that this gets passed back

Artists[0].artist
Artists[1].artist

Upvotes: 1

Views: 192

Answers (2)

Stokedout
Stokedout

Reputation: 11045

Okay here's what I used in a previous project to revise the IDs and names of inputs to allow model binding when posted to an MVC controller.

The first function takes an object and searches for all inputs, selects and textareas contained within it. The object you pass would probably be a row or div that contains all related inputs per Artist.

// Applies new id and name with correct number sequence to set fields
function reviseFieldNameAndId(obj, newNumber) {
    obj.find('input,select,textarea').each(function () {
        var parts = this.id.split(/_[\d+]__/); // Everything can be obtained from id only
        this.id = parts[0] + '_' + newNumber+ '__' + parts[1]; // Payments_0__PaymentReasonId
        this.name = parts[0] + '[' + newNumber+ '].' + parts[1]; // eg. Payments[0].PaymentReasonId
    });
}

function reviseAllFieldNamesAndIds() {
    $('#artists .row').each(function (index) {
        reviseFieldNameAndId($(this), index);
    });
}

Use the second function to go through all rows and perform the apply the new sequence.

PS - your answer is near enough the same as this but only works with artists whereas mine will work with different names and ids

Upvotes: 1

Milligran
Milligran

Reputation: 3161

I gave each dynamically added input item the same class name then used JavaScript to update and reorder every element id and name in an ordered sequence:

 $('.divArtist').each(function (i, obj) {
                     this.id = 'artists[' + i + '].artist';
                     this.name = 'artists[' + i + '].artist';
                 });

Upvotes: 0

Related Questions