0

I'm creating an observable array from JSON that comes from the server.

var ViewModel = function (data) {
            var self = this;
            self.list = ko.observableArray(data);
            self.selected = ko.observable();
}

I'm able to bind the properties with my UI

<form data-bind="with: selected">
   <input type="text" data-bind="value: Name">
   <button type="submit" class="btn btn-primary" data-bind="click: $root.create">Save</button>
</form>

I also have an edit method on click which puts the selected object into selected

self.edit = function (o) {
                self.selected(o);
            }

Code for iterating through the list:

<tbody data-bind="foreach: list">
            <tr>
                <td data-bind="text: Name"></td>
                <td><button data-bind="click: $root.edit">edit</button></td>
            </tr>
        </tbody>

The code for creating is as follows:

self.create = function (formElement) {
                $(formElement).validate();
                if ($(formElement).valid()) {
                    $.post(baseUri, $(formElement).serialize(), null, "json")
                        .done(function (o) {
                            self.list.push(o);
                        });
                }
            }

So how can I use the same form for adding an object? I'm a little confused with the data-bind on the form. I can't show the form without selecting an object.

From all the examples I have seen, it seems I have to create a ViewModel with the properties hard coded. I don't want to do that since I have many views with many properties. What can be the best approach to this?

Update

Fiddle

This is exactly what I need : CRUD but with a ViewModel that gets generated from JSON and I don't have to manually create it.

CC7589
  • 133
  • 1
  • 12
  • 1
    Could you set up a JSFiddle or something? I can't quite understand your question or problem – Ian Jun 15 '14 at 21:43
  • Take a look at the knockout mapping plugin to automatically create observerable properties on the viewmodel: http://knockoutjs.com/documentation/plugins-mapping.html – Wayne Ellery Jun 16 '14 at 00:00
  • You'll need an `Add` button to serve as the "selection" which passes a new item into `selected`. The properties of the new item could then be set in your `edit` form. – Origineil Jun 16 '14 at 03:08
  • @WayneEllery - Passing JSON to the `observableArray()` does the same without creating observables for all the properties. – CC7589 Jun 16 '14 at 06:54
  • @Origineil - I havean add button. On click event, how can I create an object similar to what I get in JSON? – CC7589 Jun 16 '14 at 06:55
  • @Ian - I have added the link for Fiddle – CC7589 Jun 16 '14 at 07:08
  • @CC7589 Yeah, I misunderstood what you were trying to do – Wayne Ellery Jun 16 '14 at 07:52
  • Something [like this](http://jsfiddle.net/3uZW7/8/) would work if the data object only contains editable properties. However, I'd prefer to see this approach used once to generate the source for a proper viewModel that you can then use. – Origineil Jun 16 '14 at 14:52
  • This [question][1] in exactly what I needed! [1]: http://stackoverflow.com/questions/6735225/knockout-js-mapping-plugin-without-initial-data-empty-form – CC7589 Jun 16 '14 at 19:37

1 Answers1

0

Maybe this would help you, http://jsfiddle.net/3uZW7/7/

function mapFactory(factory)
{
    var self = this;
    self.name = ko.observable(factory.name);
    self.isEdited = ko.observable(false);
};

var ViewModel = function (data) {
    var self = this;
    self.list = ko.observableArray();

    self.newFactory = ko.observable();
    self.addNewFactory = function()
    {
        if (self.newFactory())
            self.list.push(new mapFactory( { name: self.newFactory() } ));
    };

    self.toggleEdit = function(data)
    {
       data.isEdited( ! data.isEdited() );  
    };

    self.save = function(data)
    {
      // ajax.. etc..

        data.isEdited(false);
    };

    self.delete = function(data)
    {
     // ajax.. etc..

        self.list.remove(data);
    }
 };

var viewModel = new ViewModel;

// Call/Retrieve ajax data and push to observableArray
var retrieveDataFromAjax = [
    { 'name' : 'Mike' },
    { 'name' : 'Jack' }    
];

ko.utils.arrayForEach(retrieveDataFromAjax, function(data)
{
   viewModel.list.push(new mapFactory( data ));                         
});

ko.applyBindings(viewModel);
Fariz Azmi
  • 713
  • 1
  • 6
  • 21
  • Using this example, I still have to define my ViewModel properties. I have a very complex model and around 100 views – CC7589 Jun 16 '14 at 09:04