2

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:

  • User clicks on delete button to delete row from table. [Works]
  • Call the delete action method on the mvc controller to actualy delete the data from the database. [Works]
  • Send back new Json object containing the data of the new changed table. [Works]
  • Load the new data in my knockout viewmodel and update the UI using 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>
4
  • Can you post the code that defines this.Experiences? You almost certainly won't be able to use this. here though - the this object inside your success callback is not the same as it is within your ViewModel function... Commented Apr 9, 2013 at 9:27
  • Thanks, but I have still the same problem, I updated my question to make the problem clearer. Commented Apr 9, 2013 at 11:34
  • Where are you instantiating self.Experiences? Commented Apr 9, 2013 at 11:36
  • self.Experiences comes from my mvc4 viewmodel. it gets mapped to knockout. at this line var jsonModel = '@Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(this.Model, new Newtonsoft.Json.Converters.IsoDateTimeConverter()))'; Commented Apr 9, 2013 at 11:41

2 Answers 2

0

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());
Sign up to request clarification or add additional context in comments.

1 Comment

thank you! I know initialize everty thing with: var myViewModel = ko.mapping.fromJSON(jsonModel, {}, new ViewModel()); and self.UpdateExperienceList = function (data) { ko.mapping.fromJSON(data, {}, self.Experiences); } Finally works! Thanks!
0

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()

1 Comment

Thanks for your input but its no solution, I have updated my orginal question to simplefy my problem

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.