2012-04-20 4 views
21

Ich habe eine App, die im Moment eine Ansicht von Objekten des gleichen Modells enthält. Sie werden vom Server abgerufen, durchgeschleift und in der Liste Controller eine Add-Methodeember.js - was ist das richtige Controller/View-Muster zum Erstellen eines neuen Modells

<script> 
App.Controllers.List = Em.ArrayProxy.create({ 
    content: Ember.A([]), 
    add: function(obj){ 
    this.pushObject(obj); 
    } 
}); 
</script> 

ich auf einem Teil arbeiten bin jetzt mit dem der Benutzer ein neues Objekt erstellt, dass (nach der Validierung vorbei) wird hinzugefügt werden die Liste und auch an den Server gesendet.

Ich kann keine Beispiele für die besten Muster zum Erstellen eines neuen Objekts über ein Eingabeformular finden. Ich sehe ein paar Optionen und habe ein paar umgesetzt, aber nichts fühlt sich richtig an.

  • Erstellen einer Ansicht mit entsprechenden Formelementen und ein Verfahren zur Instanziierung das Modell aus der Formelemente mittels .get()
  • Erstellen eines Modells in der Ansicht der Inhalte und bind Formularelemente, die abgerufen verschiedenen Eigenschaften verwendet. Fügen Sie eine Methode für die Sicht auf die Controller-Array für das Hinzufügen/zum Server
  • Erstellen Sie ein Modell zu speichern, fügen Sie es dem Controller-Array und öffnen Sie sie zum Bearbeiten

ich die Funktionalität, die ich ausfechten Art kann wollen, aber ich würde lieber sicherstellen, dass ich Best Practice kenne.

Im Moment habe ich so etwas wie dieses (das ist die zweite Kugel auf meiner Liste ist)

<script> 
App.Views.ItemCreate = Em.View.extend({ 
    content: App.Models.Item.create({}), 
    templateName: 'create', 
    createButton: function(){ 

    var itemObj = this.get('content'); 
    var item = {}; 
    item.title = this.get('content').get('title'); 

    $.ajax({ 
     type: 'POST', 
     url: '/test/data.json', 
     data: item, 
     dataType: 'json', 
     success: function(responseData, textStatus, jqXHR) { 
     App.Controllers.List.add(itemObj); 
     } 
    }); 
    } 
}); 
</script> 

<script type="text/x-handlebars" data-template-name="create"> 
    {{view Em.TextField id="create-title" valueBinding="content.title"}} 
    <a href="#" {{action "createButton" }}>Create</a> 
</script> 

Jede große Hilfe

NOTES geschätzt

ich die richtige Antwort geändert haben zu Pangratz. Obwohl die anderen Antworten meine Frage direkt beantwortet haben, glaube ich, dass diejenigen, die das über Google finden, auf die Antwort Pangratz verwiesen, da es nicht nur gute MVC ist, aber es ist mehr Ember-y:

Antwort

23

Kommunikation mit dem Server ist definitiv etwas, was nicht in der Ansicht getan werden sollte. Dies ist etwas, für das ein Controller ist. Um die verschiedenen Teile der Anwendung weiter zu trennen, würde ich sogar in Erwägung ziehen, eine DataSource zu implementieren, die die AJAX-Anfragen behandelt. Diese Aufteilung macht Ihre Anwendung testbarer und jede Komponente wiederverwendbar. Die konkreten Verbindungen von View, Controller und Datenquelle werden dann über Bindings realisiert.

Der Workflow für Ihren Fall könnte die folgende sein:

  • Die Ansicht zeigt Ihre Bearbeitungsform, die‘Werte an einen Controller
  • Die Ansicht Griffe eine Aktion speichern, die den Controller zu speichern sagt gebunden sind das erstellte Objekt
  • die Controller Delegierten der Datasource die Einsparung, die dann beginnt endlich die Anfrage AJAX
  • die Steuerung gemeldet wird, wenn das Objekt gespeichert wurde

Sie sollten sich auch ember-data anschauen, was ein Client-seitiger Datenspeicher ist und alle Voreinstellungen für Sie übernimmt. Auch einen Blick auf The architecture of Ember.js apps - data und EmberJS: Good separation of concerns for Models, Stores, Controllers, Views in a rather complex application?


Ausblick:

App.View.ItemCreate = Ember.View.extend({ 
    templateName: 'create', 
    createObject: function(evt) { 
    var object = this.get('content'); 
    var controller = this.get('controller'); 
    controller.createObject(object); 
    } 
}); 

Controller:

App.Controllers.List = Ember.ArrayProxy.extend({ 
    content: [], 
    createObject: function(hash) { 
    var dataSource = this.get('dataSource'); 
    dataSource.createObject(hash, this, this.createdObject); 
    }, 
    createdObject: function(object) { 
    this.pushObject(object); 
    } 
}); 

Datasource:

App.DataSource = Ember.Object.extend({ 
    createObject: function(hash, target, callback) { 
    Ember.$.ajax({ 
     success: function(data) { 
     callback.apply(target, data); 
     } 
    }); 
    } 
}); 

Kleber alles zusammen :

App.dataSource = App.DataSource.create(); 
App.listController = App.Controllers.List.create({ 
    dataSourceBinding: 'App.dataSource' 
}); 

App.View.ItemCreate.create({ 
    controllerBinding: 'App.listController' 
}).append(); 
+1

Danke auch dafür. Ich habe bemerkt, dass ich beim Implementieren der Datenquelle etwas mit dem Umschreiben von Glutendaten begonnen habe. Ich habe das bereits in einem etwas anderen Kontext verwendet und hatte ein wenig unexpected Verhalten, ich werde es noch einmal versuchen! – joevallender

+2

Auch nur für jeden anderen bemerkt, der darüber stolpert: in der Datenquelle CreateObject-Funktion, wenn apply verwendet wird, sollte es callback.apply (Ziel, [Daten]) oder Callback.call (Ziel, Daten) und du würdest Wahrscheinlich verwenden Sie ein self/_this /, das Sie in die Ajax-Funktion anstelle der zurückgegebenen Rohdaten übergeben haben – joevallender

2

Wenn Sie möchten Folgen Sie einem strengen MVC-Modell, dann sollte das Modell niemals auf der Ansicht, sondern auf dem Controller erstellt werden. Ember ist noch sehr jung und hat immer noch keine definierten Muster, was ich tun würde, ist Ihr Modell als Inhalt der Ansicht festgelegt (wie Sie es bereits getan haben) mit allen Eingaben an die verschiedenen Modellattribute zu binden. Dann, wenn die Taste gedrückt:

createButton: function(){ 
    App.Controllers.List.create(this.get('content')); 
} 

auf dem Controller:

create: function(model) { 
    if model.valid() { //validates the model 
    model.save({ 
     onSuccess: function(response) { // callback 
     var item = App.Models.Item.create(response.item) 
     App.controllers.List.add(item) 
     } 
    }) 
    } 

Und schließlich das Modell:

save: function(options) { 
    $.ajax({ 
    type: 'POST', 
    url: '/test/data.json', 
    data: item, 
    dataType: 'json', 
    success: options.onsuccess 
    }); 
} 

Dies ist die Art und Weise andere js Rahmenbedingungen erwarten Sie arbeiten. Es fühlt sich ein wenig mehr und komplex, aber es hält die Dinge an Ort und Stelle

+0

Danke für die Antwort. Bevor Sie geantwortet haben, habe ich ein Objekt zu meinem Controller-Array hinzugefügt und dessen EditMode aufgerufen, während ich es instanziiert habe. Es funktioniert in meinem Fall, da normalerweise alles an Ort und Stelle bearbeitet würde. Ich habe es nicht ganz so schön geschrieben (und mein AJAX-POST war in Sicht!), Also werde ich es näher an deiner Version arbeiten. Sehr klar, danke. – joevallender