2010-11-02 12 views
62

Mam aplikację backbone.js (www.github.com/juggy/job-board), gdzie chcę powiązać moje dane wejściowe bezpośrednio z moim modelem (a la Sproutcore).Czy mogę powiązać dane wejściowe formularzy z modelami w Backbone.js bez ręcznego śledzenia zdarzeń z rozmyciem?

Czy jest to możliwe z Backbone.js (lub innymi narzędziami) bez faktycznego śledzenia każdego zdarzenia rozmycia na wejściach i ręcznego aktualizowania modelu? Wydaje się, że jest to dużo kodu kleju.

Dzięki,
Julien

Odpowiedz

34

Nie jestem pewien, jak to robi SC ale prawdopodobnie ich słuchać na imprezach też.

window.SomeView = Backbone.View.extend({ 
    events: { 
    "change input.content": "contentChanged" 
    }, 
    initialize: function() { 
    _.bindAll(this, 'contentChanged'); 
    this.inputContent = this.$('input.content'); 
    }, 
    contentChanged: function(e) { 
    var input = this.inputContent; 

    // if you use local storage save 
    this.model.save({content: input.val()}); 

    // if you send request to server is prob. good idea to set the var and save at the end, in a blur event or in some sync. maintenance timer. 
    // this.model.set({content: input.val()}); 
    } 
}); 
+0

Skończyło się na tym, że robię dokładnie to. Do tej pory pracuję świetnie. Jak powiedziałeś, zapisuje się przy każdej zmianie wejścia. Błędy są wyświetlane natychmiast, co jest dobre i złe (niezmodyfikowane pola wyświetlałyby błędy, które nie mogą być puste podczas tworzenia rekordu). – Julien

+2

1. można również spróbować zdarzenie blur. 2. Zastanawiam się nad tym zagadnieniem, warto byłoby mieć tablicę "powiązań" podobną do tablicy "zdarzeń", która określa aktualizacje między częściami widoku a atrybutami modelu z parametrami typu synchronizacji (at_change, at_blur itp.) . mówi podobnie do 'powiązań: [[div # title", "model.title", "change", "<-"], ["input # description", "model.description", "change", "<->" ]] lub coś w tym stylu powinno być dość łatwe do wdrożenia. – clyfe

+0

Myślę, że możesz użyć Handlebar.js jako silnika szablonowego. Ma tego rodzaju wiązania. – Julien

52

Istnieje jeszcze lepszy sposób na obsłużenie tego, jeśli model zawiera wiele właściwości w nim.

SampleView = Backbone.View.extend({ 
    el: "#formEl", 

    events: { 
     "change input": "changed", 
     "change select": "changed" 
    }, 

    initialize: function() { 
     _.bindAll(this, "changed"); 
    }, 

    changed:function (evt) { 
     var changed = evt.currentTarget; 
     var value = $(evt.currentTarget).val(); 
     var obj = {}; 
     obj[changed.id] = value; 
     this.model.set(obj); 
    } 
}); 

Istnieje zależność od elementów wejściowych o identyfikatorze identycznym z nazwą właściwości modelu.

+1

Czy var obj = {} [changed.id] = wartość; działa lepiej niż: var obj = "{\" "+ zmienił.id +" \ ": \" "+ wartość +" \ "}"; var objInst = JSON.parse (obj); – btiernay

+0

Nigdy nie powinieneś polegać na czymś w rodzaju: '" {\ "" + zmień.id + "\": \ "" + wartość + "\"} "' przynajmniej serializuj/uciec ciąg wartości, jeśli musisz. – LoG

+0

Ta sama idea została rozszerzona i zaimplementowana jako wtyczka: http://lostechies.com/derickbailey/2011/07/24/awesome-model-binding-for-backbone-js/ – JamieJag

18

myślę, że jest to odkurzacz (i być może szybciej) sposobem utworzenia obiektu z elementu wejściowego

changed: function(evt) { 
    var target = $(evt.currentTarget), 
     data = {}; 
    data[target.attr('name')] = target.val(); 
    this.model.set(data); 
}, 

bez jQuery:

changed: function(evt) { 
    var target = evt.currentTarget, 
     data = {}; 
    data[target.name] = target.value; 
    this.model.set(data); 
}, 
+2

Nie trzeba przekazywać obiektu do modelu.set(). Innymi słowy, możesz użyć następującego: this.model.set (target.name, target.value); –

1

pracuję na gorset, forma biblioteka for backbone.js zainspirowana modułem formularzy django, ale o nieco mniejszym zakresie. Nadal pracuję nad supłami, ale skończy się na githubie, gdy jest przynajmniej częściowo stabilny i funkcjonalny.

Celem gorsetu jest posiadanie łatwo subklasowanych klas pól, dzięki czemu można budować złożone dane wejściowe dla bardziej złożonych przypadków użycia (kaskadowe zaznaczenia itp.). Podejście to renderuje każde pole jako osobny widok, a widok formularza jest powiązany z modelem i używa zdarzeń zmian, rozmycia lub przesłania zdarzeń w celu zaktualizowania modelu (konfigurowalne, domyślne ustawienie "zamazywanie"). Każdy widok ma nadpisywalną funkcję getData, która domyślnie odwzorowuje funkcję .val() jquery.

Korzystając z domyślnych ustawień domyślnych i funkcji modelFormFactory, używamy gorsetu (lub jego podzestawu, który jest już gotowy) do szybkiego opracowania, zdefiniowania modelu przy użyciu sensownych nazw atrybutów, użycia modeluFormFactory i natychmiastowego interfejsu użytkownika.

+0

Chciałbym zobaczyć tę bibliotekę! Czy jest jeszcze dostępny? – bradgonesurfing

+0

Niestety, nie jest jeszcze gotowy do ogólnej konsumpcji, ale mamy nadzieję, że uda się go zdobyć w sierpniu (należy wysłać produkt najpierw, zanim będę mógł poświęcić czas na jego wyczyszczenie i uogólnienie) –

0

I stworzył następującą technikę na mojej stronie

class FooView extends MyView 

    tag: "div" 

    modelBindings: 

    "change form input.address" : "address" 
    "change form input.name" : "name" 
    "change form input.email" : "email" 

    render: -> 

    $(@el).html """ 
     <form> 
     <input class="address"/> 
     <input class="name"/> 
     <input class="email"/> 
     </form> 
    """ 

    super 

    @ 


# Instantiate the view 
view = new FooView 
    model: new Backbone.Model 

$("body").html(view.el) 

Mam szczegółowe rozszerzenia do szkieletu musisz zrobić na moim blogu

http://xtargets.com/2011/06/11/binding-model-attributes-to-form-elements-with-backbone-js/

używa tego samego stylu jak deklaratywny właściwość events dla elementów formularza wiążącego dla atrybutów modelu

i tutaj jest Rzeczywisty kod implementujący klasę dla Ciebie w coffeescript

class MyView extends Backbone.View 

    render: -> 

    if @model != null 
     # Iterate through all bindings 
     for selector, field of @modelBindings 
     do (selector, field) => 
      console.log "binding #{selector} to #{field}" 
      # When the model changes update the form 
      # elements 
      @model.bind "change:#{field}", (model, val)=> 
      console.log "model[#{field}] => #{selector}" 
      @$(selector).val(val) 

      # When the form changes update the model 
      [event, selector...] = selector.split(" ") 
      selector = selector.join(" ") 
      @$(selector).bind event, (ev)=> 
      console.log "form[#{selector}] => #{field}" 
      data = {} 
      data[field] = @$(ev.target).val() 
      @model.set data 

      # Set the initial value of the form 
      # elements 
      @$(selector).val(@model.get(field)) 

    super 

    @ 

appologies jeśli nie podoba coffeescript. Ja robię. Każdy jest inny :)

+8

Księgowanie generowanych danych nie jest szczególnie przydatne dla przykładów CoffeeScript o dowolnej wielkości - jest brzydki i trudny do odczytania, ponieważ dane wyjściowe są przeznaczone dla tłumacza, a nie do czytania. Nigdy nie pisałbyś w ten sposób JavaScript ręcznie. Z tego powodu zaskakuje mnie, że tak wiele przykładów Coffeescript robi to na końcu ze zwyczajową "JavaScript - eww!" –

+7

W dzisiejszych czasach nikogo nie uszczęśliwiasz. Po prostu napisz coffeescript raymond narzeka. Dokonaj edycji, dołączając tłumaczenie i insynuacje. Biorąc pod uwagę, że pytanie dotyczyło wiązania formy w kręgosłupie, moja odpowiedź była na temat i prawdopodobnie najbardziej idiomatyczne rozwiązanie szkieletowe. Pytanie dotyczyło głównie jquery i szkieletu, a nie javascript. – bradgonesurfing

+0

Szkielet to stary kapelusz. Powinieneś używać angularjs, jeśli chcesz mieć superaktywne wiązania. – bradgonesurfing

Powiązane problemy