Reputation: 12799
I have a strongly typed Category View, showing all Category (in a grid) ... Under that grid I have the fields to Add/Edit a new Category details: several textbox and radiobox, like : - Category Name - Category Description - Category Imagem etc
So, When the user select a Category on Grid, it fills the fields via JQuery Ajax...
$.ajax({
url: '/Category/Get',
type: 'POST',
dataType: 'json',
data: {
idCategory: ...
}
})
.success(function(category,success) {
// Update TextBox fields
$(".ajax").each(function(){
$(this).val(category[$(this).attr("id")]);
});
//Other fields ...
})
My Controller
[HttpPost]
public ActionResult Get(string idCategory)
{
if (ModelState.IsValid)
{
var _category = _categoryRepository.Get(Convert.ToInt16(idCategory));
if (Request.IsAjaxRequest())
return Json(_category);
return RedirectToAction("Index");
}
if (Request.IsAjaxRequest())
return Json(new Category());
return View();
}
It´s working fine !
But I´d like to know if it is the best way to do that... It is possible to do it another way? Maybe using Ajax.BeginForm?
Thanks
Paul
Upvotes: 1
Views: 2352
Reputation: 4313
Two possible ways to do this in my view.
1) Return a partial view with the category fields in it each time you change the selected category in the grid. Don't bother with JSON.
2) If you want to use JSON (which is how I'd probably do it), then use a framework like Knockout.JS to handle the binding. It would look something like this:
<div id="current">
Name: <input type="text" data-bind="value: Name"/><br/>
Description: <input type="text" data-bind="value: Description"/><br/>
<input type="button" value="Save" data-bind="click: Save" />
</div>
// javascript viewmodel w/ observable properties (except Id)
var Category = function(original) {
this.Id = original.Id;
this.Name = ko.observable(original.Name);
this.Description = ko.observable(original.Description);
this.asJson = function() {
return {
Id: this.Id,
Name: this.Name(), // call observables as method to get underlying value
Description: this.Description()
};
};
this.Save = function() {
$.post("/Category/Update", $.toJSON(this.asJson()));
};
}
$.post('/Category/Get', { idCategory: ... }, function(response) {
var viewModel = new Category(response);
ko.applyBindings(viewModel, $("#current"));
}, "json");
Your action could probably be simplified to
[HttpPost]
public ActionResult Get(int idCategory)
{
var category = _categoryRepository.Get(idCategory) ?? new Category();
return Json(category)
}
Then to save just do whatever you normally do on the server
[HttpPost]
public ActionResult Update(Category updated)
{
var category = _categoryRepository.Get(updated.Id);
// todo: update category with values from updated model
}
Edit
If you don't want to call applyBindings multiple times, you can use templates instead. (I didn't test this code but it should be very close.)
<div id="current" data-bind="template: {name: 'categoryTemplate', data: Current}"/>
<input type="button" value="Save" data-bind="click: Save" />
<script type="text/html" id="categoryTemplate">
Name: <input type="text" data-bind="value: Name"/><br/>
Description: <input type="text" data-bind="value: Description"/>
</script>
// javascript viewmodel w/ observable properties (except Id)
var Category = function(original) {
this.Id = original.Id;
this.Name = ko.observable(original.Name);
this.Description = ko.observable(original.Description);
this.asJson = function() {
return {
Id: this.Id,
Name: this.Name(), // call observables as method to get underlying value
Description: this.Description()
};
};
}
var viewModel =
{
Current = ko.observable({}),
Save = function() {
$.ajax({
url: "/Category/Update",
data: $.toJSON(this.Current().asJson()),
type: "POST",
contentType: "application/json; charset=utf-8"
});
}
};
$.post('/Category/Get', { idCategory: ... }, function(response) {
viewModel.Current(new Category(response));
}, "json");
$(function(){
ko.applyBindings(viewModel, $("#current"));
});
Upvotes: 2