2016-04-15 18 views
0

Ich habe eine Ember-Komponente mit einer Vorlage, die eine Tabelle enthält. In meiner Komponente möchte ich Ajax-Anrufe an einen Drittanbieter-Dienst ausgeben und einige Daten abrufen. Nachdem ich diese Daten erhalten hatte, musste ich einen weiteren nachfolgenden Ajax-Aufruf basierend auf der Eingabe durchführen. Da dies einige Zeit dauern würde, möchte ich die Ansicht nach und nach aktualisieren, wenn der Ajax beendet ist. In einem visuellen Sinn - dies würde eine neue Zeile zu der Tabelle hinzufügen, nachdem eine Anfrage verarbeitet wurde.Dynamischer Inhalt wird geladen

Momentan erlaubt uns ember nur, ein Array-Objekt über seine model()-Methode im Router zu übergeben.

Ich schaute in mehrere Projekte wie List-view, aber es löst nicht das oben erwähnte Problem.

EDIT: -

Im Folgenden finden Sie, was ich derzeit tue -

import Ember from 'ember'; 
export default Ember.Route.extend({ 
    model() { 
     var list = []; 
     var promise = $.ajax({ 
      type: 'GET', 
      url: 'thirdPartyService' 
     }); 
     promise = promise.then(function(data){ 
      data = JSON.parse(data); 
      return data[1]; 
     }); 
     promise.then(function(data){ 
      for (var i = 0; i < data.length; i++) { 
       var idea = data[i]; 

       var url = "thirdPartyService"; 
       var secondPromise = $.ajax({ 
        type: 'GET', 
        url: url, 
        dataType: "text" 
       }); 
       secondPromise = secondPromise.then(function(data){ 
        var result = x2js.xml_str2json(data); 
        return result; 
       }); 
       secondPromise.then(function(data){ 
        list.pushObject(item); 
       }); 
       return secondPromise; 
      } 
     }); 
     return list; 
    } 
}); 

Meine Vorlage

<tbody> 
{{#each model as |idea|}} 
    <tr> 
    <td><input type="checkbox" name="id" value="{{idea.id}}"></td> 
    <td>{{idea.field4}}</td> 
    <td>{{idea.field5}}</td> 
    <td>{{idea.field}}</td> 
    <td>{{idea.field2}}</td> 
    <td>{{idea.field3}}</td> 
    </tr> 
{{/each}} 
</tbody> 

Die Ember Ansicht gerendert wird, wenn die Liste ändert. Was ich tun möchte, ist - eine Zeile zur Tabelle hinzufügen, wenn list.pushObject(item); aufgerufen wird. Derzeit - ich sehe, dass die Ansicht wartet, bis alles zurückgegeben wird.

Auch diese Anwendung ist eine Elektronen-App - deshalb habe ich kein Backend per sag und verwende keine Glutendaten. Ich rufe einige Dienste von Drittanbietern an, also sind keine Glut-Modelle beteiligt.

+1

Uhm. Ember erlaubt alle Arten von Bindungen. Muss nur in der Steuerung oder Route vordefiniert sein. Bitte zeigen Sie uns, was Sie versucht haben oder wonach Sie suchen. Die aktuelle Frage ist zu weit gefasst, um sie zu beantworten oder Annahmen zu treffen. –

+0

@kristjabreinhold Ich verbesserte die Antwort mit dem aktuellen Arbeitsmodell und einigen Details meiner Umgebung (Ich baue eine Elektronen-App) – Chan

Antwort

1

Update:

Demo: https://ember-twiddle.com/eb79994c163dd1db4e2580cae066a318

In dieser Demo herunterladen ich Ihre Github Daten, und die Liste der repos, so dass das Modell Haken kehrt, wenn beide api-Aufruf zurück ... und schließlich wird die Liste der Repo-Namen bereitstellen.

Mit loading.hbs erscheint die Lade-Nachricht automatisch, bis der Modell-Haken gelöst verspricht.

In Ihrem Code ist es wahrscheinlich nicht die beste Methode, die Variable zu überschreiben, weil Sie eine Variable überschreiben, die noch nicht aufgelöst ist.

Wenn Sie eine bessere Benutzererfahrung wünschen, am besten, wenn Sie nur einen Ajax-Aufruf im Modell haben und dieses Versprechen zurückgeben ... also enthält Ihr Modell das erste vielversprechende Ergebnis ... und Sie können diese Daten verwenden ein Versprechen im Controller auslösen und die Liste herunterladen, so dass der Benutzer den Header der Tabelle und die Lade-Nachricht sehen kann, bis die Liste heruntergeladen ist.

Demo mit einer zweiten Seite erweitert: https://ember-twiddle.com/eb79994c163dd1db4e2580cae066a318


Wenn Sie mit mehr Modelle auf Ihrer Seite zu tun haben, ich würde sie in der Route-Handler, mit RSVP.hash herunterladen.

// for example: app/routes/books.js, where books are the main model 
import Ember from 'ember'; 

export default Ember.Route.extend({ 

    model() { 
    return Ember.RSVP.hash({ 
     books: this.store.findAll('book'), 
     authors: this.store.findAll('author'), 
     libraries: this.store.findAll('library') 
    }); 
    }, 

    setupController(controller, model) { 
    const books = model.books; 
    const authors = model.authors; 
    const libraries = model.libraries; 

    this._super(controller, books); 

    controller.set('authors', authors); 
    controller.set('libraries', libraries); 
    }, 
}); 

Im obigen Beispiel haben Sie model (mit der Liste der Bücher), authors und libraries in Ihrem Controller, so dass Sie uns darauf, diese Arrays Komponenten passieren können.

Verwenden Sie Ember Data, um auf Ihre Server-API oder den Dienst eines Drittanbieters zuzugreifen? In diesem Fall können Sie den Dienst store in Ihre Komponente injizieren und dort wie im Routen-Handler verwenden.

Andere Option mit Abschluss Aktionen, so dass Ihre Aktionen in Controller und Sie können diese Aktionen von Komponenten aufrufen, so dass die ganze Komponente nur für das Anzeigen von Daten und anderen Schnipsel verantwortlich wäre.

Im folgenden Beispiel erstellen wir eine eigenständige Komponente, wo Sie eine Schaltfläche haben, um eine Aktion auszulösen, die Daten vom Server herunterlädt, mit dem klassischen jquery ajax Aufruf, der in eine Verheißung gehüllt ist Kette diese Versprechen und feuern sie in einer Reihe.

eine Komponente

$ ember g component my-component 

Die Vorlage app/templates/components/my-components.hbs, erstellen mit einem Knopf, eine Flagge und der Liste.

<button {{action 'downloadSomething'}}>Download</button> 

in progress: {{downloadInProgress}} 

{{#each downloaded as |item|}} 
    {{item.name}} 
{{/each}} 

Die angeschlossene js app/components/my-components.js

import Ember from 'ember'; 

const { $ } = Ember; 

export default Ember.Component.extend({ 

    downloaded: [], 

    actions: { 

    downloadSomething() { 
     this.set('downloadInProgress', true); 

     this._getData('http://localhost:8080').then(
     (response) => { 
      this.set('downloadInProgress', false); 
      this.get('downloaded').pushObjects(response.contacts); 
     }, 
     (error) => { 
      // some error handling... 
     } 
    ); 
    } 
    }, 

    // this function wraps the ajax call in a Promise 
    _getData(url) { 
    return new Ember.RSVP.Promise((resolve, reject) => 
     $.ajax(url, { 
     success(response) { 
      resolve(response); 
     }, 
     error(reason) { 
      reject(reason); 
     } 
     }) 
    ); 
    } 

}); 

In der Ajax-Antwort-Datei, drücken wir die zurückgegebenen Objekte in der downloaded Array, so wäre es in die Liste immer hinzugefügt.

+0

Ich aktualisierte meine Frage mit Antworten auf einige der Fragen, auf die Sie hingewiesen haben. In meinem Fall - das Problem ist, dass ich eine weitere Ajax-Anfrage machen muss, nachdem Sie die Daten von der ersten Ajax-Anfrage iterativ bekommen haben. Aus diesem Grund möchte ich das Rendering von 'downloaded' hinzufügen, das auftritt, wenn eine Iteration abgeschlossen ist (da ein Element zum' heruntergeladenen' Array hinzugefügt werden kann). – Chan

+0

Der Model Hook wartet immer darauf, das Versprechen zu lösen, also läuft der Code wird angehalten, bis alle Versprechen zurückgegeben und aufgelöst wurden ... Sie können 'loading.hbs' verwenden, um einen Spinner anzuzeigen, bis das Modell aufgelöst wurde ... Ich habe meine Antwort mit einem Ember-Twiddle-Beispiel aktualisiert ... – Zoltan

+0

Demo um eine Sekunde erweitert Seite: https://ember-twiddle.com/eb79994c163dd1db4e2580cae066a318 – Zoltan

Verwandte Themen