2012-09-26 15 views
11

Zajmuję się tworzeniem aplikacji WWW jQuery Backbone.js.
Tak jak w Adobe Flex, zaimplementowałem dwukierunkowe powiązanie danych w mojej aplikacji dla elementów wejściowych/widżetów . Tak, każdy element wejściowy/widget zna odpowiednią nazwę atrybutu modelu i modelu.
Gdy użytkownik kliknie kartę lub wprowadzi, wartość pola zostanie automatycznie przypisana do modelu.Dwukierunkowe powiązanie danych w backbone.js

container.model.set(this.attrName, this.value, options); // command 1 

W przeciwnym kierunku, kiedy model jest aktualizowany od backend, widok elementu wejściowego/widget powinien automatycznie się aktualizacja:

container.model.bind("change:"+ this.attrName, this.updateView, this); // command 2 

Problemem jest:
Kiedy użytkownik wchodzi enter, a model jest automatycznie aktualizowany, również wywoływana jest "change: abc" i wywoływana jest this.updateView, nie tylko wtedy, gdy nowy model pochodzi z zaplecza .

Moje rozwiązanie do tej pory polegało na przekazaniu opcji "source: gui" przy ustawianiu wartości modelu po naciśnięciu klawisza enter (polecenie 1) i sprawdzeniu tego w mojej metodzie updateView. Ale nie jestem zadowolony z tego rozwiązania.

Czy ktoś ma lepsze rozwiązanie? dziękuję z góry
Wolfgang

Aktualizacja:
Gdy opcja cichy: prawda jest przekazywana, metoda sprawdzania poprawności modelu nie jest wywoływana, więc że nie pomaga. Zobacz źródło backbone.js 0.9.2:

_validate: function(attrs, options) { 
    if (options.silent || !this.validate) return true; 

Odpowiedz

7

Od strony backbone.js:

A będzie wyzwalany "zmiana" zdarzenie, chyba {cichy: true} jest przekazywana jako opcja

options.silent = true; 
container.model.set(this.attrName, this.value, options); 

Aktualizacja: Dodano nowy komentarz do Twojego pytania, więc po prostu uzupełnić moją odpowiedź do ustalania nowego zastosowania CAS e (przepływ walidacja), które wymienione:

var ExtendedModel = Backbone.Model.extend({ 
    uiChange : false, 
    uiSet: function (attributes, options, optional) { 
     this.uiChange = true; 
     this.set(attributes, options, optional); 
     this.uiChange = false; 
    } 
}); 

var MyModel = ExtendedModel.extend({ 
}); 

var model = new MyModel(); 
model.on('change:name', function(){ 
    console.log('this.uiChange: ', this.uiChange); 
}); 

//simulates the server side set 
model.set({name:'hello'}); 

//simulates the ui side set you must use it to set from UI 
model.uiSet({name:'hello2'}); 
+0

Dziękuję Daniel. Ale z tą opcją "sprawdzanie poprawności" nie jest wywoływane. Więc to mi nie pomaga. –

+0

Cześć Wolfgang, Widziałem twoją nową aktualizację i dodałem rozwiązanie. =) –

6

Dwukierunkowe wiązanie oznacza po prostu, że:

  1. Kiedy właściwości w modelu aktualizowane, więc nie UI.
  2. Po zaktualizowaniu elementów interfejsu zmiany są propagowane z powrotem do modelu .

Kręgosłup nie ma „pieczony w” Wdrożenie 2 opcji (choć z pewnością można to zrobić za pomocą detektorów zdarzeń)

w sieci szkieletowej, możemy łatwo osiągnąć opcję 1 wiążąc widokiem na " render "metoda" do "zmiany" modelu. Aby osiągnąć opcję 2, musisz również dodać detektor zmian do elementu wejściowego i wywołać model.set w module obsługi.

check (jsfiddle.net/sunnysm/Xm5eH/16)js przykładowy przykład z dwustronnym wiązaniem skonfigurowanym w Backbone.

0

Chciałem zobaczyć, jaki kod barebones będzie miał dwukierunkowe powiązanie z Backbone.js. To właśnie wymyśliłem:

var TwoWayBoundView = Backbone.View.extend({ 
    initialize: function(options) { 
     this.options = _.defaults(options || {}, this.options); 
     _.bindAll(this, "render"); 
     this.model.on("change", this.render, this); 
     this.render(); 
    }, 

    events: { 
     "change input,textarea,select": "update" 
    }, 

    // input updated 
    update: function(e) { 
     this.model.set(e.currentTarget.id, $(e.currentTarget).val()); 
    }, 

    // model updated...re-render 
    render: function(e) { 
     if (e){ 
      var id = Object.keys(e.changed)[0]; 
      $('#'+id).val(e.changed[id]); 
     } 
     else{ 
      _.each(this.model.attributes, function(value, key){ 
       $('#'+key).val(value); 
      }); 
     } 
    } 
}); 

a użycie:

var model = new Backbone.Model({ prop1: "uno 1", prop2: "dos 2", prop3: "3" }); 
var view = new TwoWayBoundView({ 
    el: "#myContainer", 
    model: model 
}); 

Oto jsbin do niego: http://jsbin.com/guvusal/edit?html,js,console,output

używałem bibliotek, które to zrobić, takie jak epoksydowe. js (tylko min. 11k). I jest jeszcze kilka innych, które polecam na długo przed użyciem powyższego kodu dowodu.

byłbym zainteresowany potencjalnych pułapek i ulepszeń, które mogą być wykonane z klasą TwoWayBoundView powyżej (ale nic poza podstawowym wiążącej prosimy dwukierunkowych! Czyli ja nie szukasz więcej funkcji dodać.)

Powiązane problemy