c# - MVC adding table row with binding on a complex viewmodel -


in view model, there list of element contains table of text inputs.

view model > list of element > table > lots of text inputs

all of generated in view via editortemplates.

everything bound view when load (mvc creating right ids , names of each input. want add , delete rows , have binding updated. means, right numbers updated in ids , name.

i have idea of how pure javascript, dirty , pain update when things change. html helpers or model binder haven't found way yet!

anyone have idea of how that?

edit : apparently have more chance answered if post lots of code detail... in complex case, that's going long, hang on!

here view model. (keep in mind code dumbed down version)

public class mvcviewmodel {     public list<activityelement> activityelementlist { get; set; } }  public abstract class activityelement { }  public class step : activityelement {     public step()     {         this.id = guid.newguid();         this.label = "basic step";     }      public step(string label, abstractinput input)         : this()     {         this.label = label;         this.input = input;     }      public guid id { get; set; }     public string label { get; set; }     public abstractinput input { get; set; } }  public abstract class abstractinput {     public object value { get; set; } }  public class gridinput : abstractinput {     public list<gridcell> headerlist { get; set; }     public list<gridrow> rowlist { get; set; } }  public class gridrow {     public list<gridcell> celllist { get; set; } }  public class gridcell {     public string columnname { get; set; }     public abstractinput input { get; set; } }  public class textinput: abstractinput {     public textinput(string value)     {         this.value = value;     } } 

alright! if somehow still me, that's good! have put them in order used in particular case.

to dumb down, view model contains list of step. first step contains gridinput abstractinput property. grid contains rows , each rows contains cells. case, let each cell contains textinput abstractinput.

now, on view, when displayed editortemplates , htmlhelpers, ids , names of inputs (therefor binding good), shown here in html output :

<td>     <input id="activityelementlist_0__input_rowlist_0__celllist_0__input_modeltype" name="activityelementlist[0].input.rowlist[0].celllist[0].input.modeltype" type="hidden" value="knockout_binding_prototype.models.textinput">     <input id="activityelementlist_0__input_rowlist_0__celllist_0__input_value" name="activityelementlist[0].input.rowlist[0].celllist[0].input.value" type="text" value="cell 1 row 1"> </td> <td>     <input id="activityelementlist_0__input_rowlist_0__celllist_1__input_modeltype" name="activityelementlist[0].input.rowlist[0].celllist[1].input.modeltype" type="hidden" value="knockout_binding_prototype.models.textinput">     <input id="activityelementlist_0__input_rowlist_0__celllist_1__input_value" name="activityelementlist[0].input.rowlist[0].celllist[1].input.value" type="text" value="cell 2 row 1"> </td> 

what trying here, able add , delete row table. easy... hard part making sure binding (ids , names) still good. in case of particular html output, if delete first row, need ids , names of second row, become equivalent first row ids , name.

i have been trying find generic way it, , try , make javascript less possible. ideas pondered, don't afraid something!

edit 2 : ok, far deleting rows go, decided hide delete row , flag deleted, biding remains good. adding row simple in javascript, searching way without javascript (or little bit).

here update in view model delete flag.

public class gridrow {     public gridrow()     {         isdeleted = false;     }      public list<gridcell> celllist { get; set; }     public bool isdeleted { get; set; } } 

try way without buggy js html modifications. can delete way well. can decide if want save model on every add/delete call or save after changes.

models:

public class samplemodel {     public list<itemmodel> items { get; set; }      public samplemodel()     {         items = new list<itemmodel>();     } }  public class itemmodel {     public int id { get; set; }     public string name { get; set; } } 

controller:

 [httppost]  public actionresult add(samplemodel model)  {         model.items.add(new itemmodel { name = "new item" });         return partialview("items");  }   public actionresult index()  {         var model = new samplemodel(); // or model         return view(model);  }   [httppost]  public actionresult index(samplemodel model)  {         // save model db         return redirecttoaction("index");  } 

index.cshtml

@model samplemodel  @using (html.beginform()) {     <div id="container">         @html.partial("items", model)     </div>     <a id="add" href="javascript:void(0);">add</a>     <button type="submit">save</button> }  <script src="jquery.js"></script> <script type="text/javascript">     $(function () {         $('#add').on('click', function () {             $.post('@url.action("add")', $('form').serializemodel(), function(html) {                 $('#container').html(html);             });         });     });      $.fn.serializemodel = function () {         var model = {};         $(this).serializearray().map(function (item) {             model[item.name] = item.value;         });         return model;     };  </script> 

items.cshtml:

@model samplemodel  <table>     @for (var = 0; < model.items.count; i++)     {         <tr>             <td>                        @html.hiddenfor(m => model.items[i].id)                 @html.textboxfor(m => model.items[i].name)             </td>         </tr>     } </table> 

Comments

Popular posts from this blog

android - Get AccessToken using signpost OAuth without opening a browser (Two legged Oauth) -

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: mockito -

google shop client API returns 400 bad request error while adding an item -