Reputation: 23
I use mvc4 and entityframework in combination with knockout. I also use knockout mapping. But I run into a problem wich I cannot get solved.
What I want to achieve:
ko.mapping.fromJS() and ko.applyBindings()
[Does not
work and I am realy lost here]It looks like I totaly lost the reference to my list of Experiences wich I use to databind and foreach my table with. And I think it has to do with the way I call my deletemethod from within the foreach loop.
It also looks like the javascript 'trick' with var self = this;
doesnt work to get my reference to the correct data.
Here follows my code I use for now to give you all a better idea of the situation. If more information is needed please let me know.
These are my mvc viewmodels:
public class ExperienceOverviewModel
{
public ExperienceModel selectedExperience { get; set; }
public List<ExperienceModel> Experiences { get; set; }
}
public class ExperienceModel
{
public int ExperienceId { get; set; }
public DateTime DateFrom { get; set; }
public DateTime DateUntil { get; set; }
public string Description { get; set; }
public string Employer { get; set; }
public decimal Hours { get; set; }
public int PersonId { get; set; }
public bool? Secondment { get; set; }
public string Title { get; set; }
}
This is my table where I foreach databind the experiences using knockout:
</table>
<thead>
</thead>
<tbody data-bind="foreach: Experiences()">
<tr>
<td data-bind="text: Employer"></td>
<td data-bind="text: Description"></td>
<td data-bind="text: DateFrom"></td>
<td data-bind="text: DateUntil"></td>
<td data-bind="text: Secondment"></td>
<td>
<a href="#" data-bind="click: function(data, event){ $root.EditExperienceModal(data); }"><i class="icon-edit"></i></a>
</td>
<td>
<a href="#" data-bind="click: function(data, event){ $root.ConfirmDeleteExperienceModal(data);}"><i class="icon-remove"></i></a>
</td>
</tr>
</tbody>
</table>
My knockout viewmodel where I want to call ko.mapping.fromJS() and ko.applyBindings()... Here it goes fubar....
function ViewModel() {
this.DeleteExperience = function (experience) {
$.ajax({
type: "post",
contentType: "application/json",
url: "/Experienced/Delete/" + this.selectedExperience.ExperienceId(),
data: ko.toJSON(self.selectedExperience),
error: function (xhr, status, error) {
},
success: function (response) {
ko.mapping.fromJS(response, ?? this.Experiences ??); <---- ???
ko.applyBindings(?????); <---- ???
}
});
}
}
$(function () {
var jsonModel = '@Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(this.Model, new Newtonsoft.Json.Converters.IsoDateTimeConverter()))';
var mvcModel = ko.mapping.fromJSON(jsonModel);
var myViewModel = new ViewModel();
g = ko.mapping.fromJS(myViewModel, mvcModel);
ko.applyBindings(g);
});
* -- UPDATED -- *
To clarify more here is what I have simplyfied: When I get the results back from the AJAX call I get the following error:
Object # has no method 'Experiences'
<table class="table table-striped">
<tbody data-bind="foreach: Experiences()">
<tr>
<td data-bind="text: Employer"></td>
<td data-bind="text: Description"></td>
<td data-bind="text: DateFrom"></td>
<td data-bind="text: DateUntill"></td>
<td data-bind="text: Secondment"></td>
<td>
<a href="#" data-bind="click: $root.DeleteExperience"><i class="icon-remove"></i></a>
</td>
</tr>
</tbody>
</table>
<script type="text/javascript">
function ViewModel() {
var self = this;
self.DeleteExperience = function (experience) {
$.ajax({
type: "post",
contentType: "application/json",
url: "/Experienced/Delete/" + experience.ExperienceId(),
data: ko.toJSON(experience),
error: function (xhr, status, error) {
console.log(error);
},
success: function (response) {
$('#confirmDeleteModal').modal('hide');
self.UpdateExperienceList(response);
}
});
}
self.UpdateExperienceList = function (data) {
self.Experiences(data); <---- ?????
}
}
$(function () {
var jsonModel = '@Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(this.Model, new Newtonsoft.Json.Converters.IsoDateTimeConverter()))';
var mvcModel = ko.mapping.fromJSON(jsonModel);
var myViewModel = new ViewModel();
g = ko.mapping.fromJS(myViewModel, mvcModel);
ko.applyBindings(g);
});
</script>
Upvotes: 2
Views: 5524
Reputation: 15999
In your self.UpdateExperienceList
function, try the following:
self.UpdateExperienceList = function(data) {
ko.mapping.fromJSON(data, {}, self);
};
This will update the properties on the self
object based on the data from the server.
Your initial creation of the view model also looks wrong to me. I would have though you wanted something more like the below:
var myViewModel = ko.mapping.fromJSON(jsonModel, {}, new ViewModel());
Upvotes: 0
Reputation: 1078
I don't think you need to call ko.applyBindings(?????);
again. You should define explicitly your view model:
function MyModel() {
var self = this;
self.Data = ko.observableArray([{"Name": "Lionel Messi", "Occupation": "Football player"}, {"Name": "Jason Mraz", "Occupation": "Singer"}, {"Name": "Nicolas Cage", "Occupation": "Film Actor"}]);
self.update = function(data) {
self.Data(data);
}
}
$(function(){
var model = new MyModel();
ko.applyBindings(model);
});
As you see I define self.update
, you just invoke this function and update your data and in case you want to remove a row from table, you just splice
that row out of self.Data()
Upvotes: 0