2

I am working on a asp.net mvc-5 project. I have following c# model:

public class Settings
{
    public int Id { get; set; }

    public string Name { get; set; }

    public string Value { get; set; }

    public int ParentId { get; set; }

    public List<Settings> SubSettings { get; set; }
}

I am rendering this model on razor view by using EditorTemplates as explained here. Now i want to add remove Settings node dynamically like:

enter image description here

When we click on red button the element should get deleted (which is quite simple and i already implemented it) and when we click on green button the node should get added to its appropriate place (here i want your help).

The node should added is such a way that default model binder can map it to its right place, can anyone please explain me how can i do this?

1
  • Unfair deed - I compensated - next time if you find such situation, do it similarly. Commented Aug 14, 2014 at 8:05

3 Answers 3

4

The key to ensuring dynamically added elements post back correctly for binding is to use an indexer. One way to do this is to create the elements representing the new object, giving them a fake indexer (so this one does not post back) and then cloning the elements and updating the index. For example

View

<div id="NewSetting" style="display:none">
  <tr>
    <td><input type="text" name="Settings[#].ID value /></td>
    <td><input type="text" name="Settings[#].Name value /></td>
    <td>.....</td> // more properties of Settings
    <td><input type="hidden" name="Settings[#].Index" value ="%"/></td>
  </tr>
</div>

Note the use of a dummy indexer to prevent this one being posted back

Script

$(AddButton).click(function() {
  var index = // assign a unique value
  var clone = $('#NewSetting').clone();
  // Update the index of the clone
  clone.html($(clone).html().replace(/\[#\]/g, '[' + index + ']'));
  clone.html($(clone).html().replace(/"%"/g, '"' + index  + '"'));
  $(SomeElement).append(clone);
}

Obviously change AddButton and SomeElement selectors to suit your needs. You will also need to ensure your editor template for creating existing Settings include the Settings[].Index property.

Sign up to request clarification or add additional context in comments.

3 Comments

The name attribute of Luck node contains value Settings[1].SubSettings[0].SubSettings[0].SubSettings[0].Name and your dummy node contain index for only one level, how can we determing the current level of the node?
That gets a bit more difficult, especially if its a never ending hierarchical structure. I think you would actually need to create the html elements that I hardcoded above using jquery based on the current hierarchical level.
First thoughts would be to get the Setting elements associated with the Add button, extract their name attributes - e.g. var name=$(this).prev().attr('name') - which might be Settings[2].SubSettings[1].Name then use `.split('.') to extract the parts and construct a new name attribute which could be used to dynamically create new elements
0

I would recommend you not to add/delete the nodes but hide/show them.

Include all the possible nodes in your model and use jquery to show and hide when the buttons are clicked.

2 Comments

But what it a user have 20 skills they want to add and you only hide 15
Add any existing items marked as Deleted items still post back so they wont be deleted in the repository!
0

You can do this via Javascript. You can use jQuery to clone the an existing dom element then change the name. Or you could you a Ajax request to get the new HTML see this post for an example.

So you HTML/View need to contain a index for each dynamic item e.g.

<input type="checkbox" name = "Foo[0].Skills" value="true"/>
<input type="checkbox" name = "Foo[1].Skills" value="true"/>
<input type="checkbox" name = "Foo[2].Skills" value="true"/>

Alternatively you could use a JavaScript template engine to dynamically as new HTML form elements such as http://handlebarsjs.com/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.