Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

knockout - cannot apply bindings multiple times to the same element

I need to fill my trip table with data from two sources: from server using GET when the page loads (to have user's archive trips) and from observable values (when a user adds a new trip). Can I somehow merge those two scripts so that they apply bindings only once? Right now I get an error: You cannot apply bindings multiple times to the same element

<div class="panel panel-default">
  <div class="panel-heading">
    <h3 class="panel-title">Add a trip</h3>
  </div>
  <div class="panel-body">
    <div class="form-group">
        <label for="from">From</label> 
        <input type="text" class="form-control" id="from" name="from" placeholder="From" data-bind="value: from">
    </div>
    <div class="form-group">
        <label for="to">To</label> 
        <input type="text" class="form-control" id="to" name="to" placeholder="To" data-bind="value: to">
    </div>
    <a class="btn btn-primary btn-lg"  role="button" data-bind="click: add()" >Add</a>
  </div>
</div>


<div class="panel panel-default">
    <div class=panel-heading>Your trips</div>
    <table class=table>
        <thead>
            <tr>
                <th>From</th>
                <th>To</th>
            </tr>
        </thead>
        <tbody data-bind="foreach: records">
            <tr>
                <td data-bind="text: from"></td>
                <td data-bind="text: to"></td>
            </tr>
        </tbody>
    </table>
</div>


<script type="text/javascript" src="js/knockout-3.4.0.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>


<script type="text/javascript">
var AppViewModel = function() {
  this.from = ko.observable();
  this.to = ko.observable();
  this.records = ko.observableArray();

};
var model = new AppViewModel();


model.add = function() {
    model.records.push({ 
    from: model.from(),
    to: model.to()
  });


//sending data to server
   var data = 
            {
                from : this.from(), to : this.to(), date : this.date(),  price : this.price(), freeSeats : this.freeSeats()           
            }
            alert(data);

        $.post("/data", data, function(response)
        {

        })

}

ko.applyBindings(model);

</script>

<script>
    function tripModel() {
        this.records = ko.observableArray([]);

        $.getJSON("/usersTrips", function(data) {

          self.records(data);

        })
    }
    ko.applyBindings(new tripModel());
</script>
like image 679
suue Avatar asked Sep 26 '22 14:09

suue


1 Answers

Give the relevant elements IDs and then apply the models to only those DOM elements. For example,

Html:

<div id="add-trip" class="panel panel-default">

<div id="your-trips" class="panel panel-default">

And the binding:

ko.applyBindings(model, document.getElementById("add-trip"));

ko.applyBindings(new tripModel(), document.getElementById("your-trips"));

JSFiddle Example:

https://jsfiddle.net/hellobrett/49xaqj46/1/

JSFiddle example going the other direction:

https://jsfiddle.net/hellobrett/49xaqj46/2/

Reference:

http://knockoutjs.com/documentation/observables.html

In case you’re wondering what the parameters to ko.applyBindings do,

  • The first parameter says what view model object you want to use with the declarative bindings it activates

  • Optionally, you can pass a second parameter to define which part of the document you want to search for data-bind attributes. For example, ko.applyBindings(myViewModel, document.getElementById('someElementId')). This restricts the activation to the element with ID someElementId and its descendants, which is useful if you want to have multiple view models and associate each with a different region of the page.

like image 136
Brett Avatar answered Oct 31 '22 08:10

Brett