2016-04-14 11 views
2

Ich arbeite mit einer Webanwendung, die es Designern ermöglicht, Seiten zu erstellen, indem sie html in einer Kombination mit angularjs-Anweisungen schreiben, die von mir und anderen Entwicklern erstellt werden. Ich kämpfe mit dem besten Weg, die Direktiven mit Daten zu füllen.AngularJS selbsterhaltende Direktiven für Designer

Der erste Versuch bestand darin, alle Anweisungen vollständig eigenständig zu halten. So eine Produktseite zum Beispiel könnte wie folgt aussehen (mit eigenen HTML um all dies - links für Klarheit out):

<product> 
    <product-information></product-information> 
    <product-image></product-image> 
    <product-quantities></product-quantities> 
    <product-add-to-cart-button></product-add-to-cart-button> 
</product> 

Wenn die Richtlinien Daten benötigen (was fast alle tun) sie einen Dienst nutzen würde Rufen Sie eine Web-API auf und erhalten Sie die Daten, die sie benötigen. Bei diesem Ansatz sind einige Probleme aufgetreten.

  1. Die Anweisungen benötigen oft Informationen von einem Elternteil oder Geschwister. Im folgenden Beispiel benötigt product-image wahrscheinlich die ProductID, damit das richtige Image erstellt werden kann. In diesem Fall muss ich darauf vertrauen, dass diese Informationen aus einem querystring-Parameter oder einem Speicher in einem angularJS-Dienst abgerufen werden, der anfänglich von der übergeordneten Direktive gefüllt wird.
  2. Viele API-Aufrufe. Mit jeder Anweisung, die eigene API-Aufrufe macht, komme ich jetzt mit Seiten, die 15+ API-Aufrufe zum Laden haben, und das kann mit der Zeit wachsen. Auch wenn viele der Daten eng verwandt sind (sogar in der gleichen Datenbanktabelle). Offensichtlich ist das weniger als ideal.

Also habe ich angefangen, meinen Ansatz mit dem zweiten Durchlauf zu ändern. Nun sind die Direktiven wie eine Baumstruktur aufgebaut, wobei jede Direktive erwartet, dass ihre Datenanforderungen über ein Attribut übergeben werden. Hier ein Beispiel:

<product-image product-url="vm.product.imageUrl" ng-if="vm.product"></product-image> 

Dies löst das Problem # 2 zu viele API und Datenbank-Anrufe aber macht zu viele Interna an die Designer. Jetzt muss der Designer wissen, dass er die Produkt-URL eingibt und muss verstehen, dass hinter den Kulissen ein Produkt steckt. Er muss vielleicht sogar ein bisschen angularJS (ng-if) verstehen. Ich habe dieses Muster auch in Angular2 mit Inputs sehr oft benutzt. Scheint gut für Entwickler, aber nicht für vom Designer verwendete Anweisungen, wir wollen die inneren Abläufe und die Komplexität verbergen und dem Designer die Möglichkeit geben, das Layout zu steuern.

Schließlich erwäge ich, mit dem übergeordneten Controller alles zu füllen, was auf der Seite benötigt werden könnte. Dann verwenden alle untergeordneten Anweisungen nur einen Dienst wie sie jetzt sind, aber anstatt eine API aufzurufen, sind die Daten bereits geladen. Die Anweisungen bleiben einfach und weitgehend eigenständig, aber ihre Daten werden von einem übergeordneten Element ausgelöst. Das einzige Problem, das ich dabei habe, ist, dass wir möglicherweise eine Menge Daten laden, die ungenutzt sind, weil die Richtlinien vom Designer nicht verwendet werden. Aber ich denke, das ist ein notwendiger Kompromiss.

Hat jemand etwas ähnliches gebaut, gibt es irgendwelche möglichen Ansätze, die ich vermisse?

+0

ich kein Problem mit einem Dienst zu sehen, die als Modell dient und Griffe alle APIs.Was ist das Problem bei diesem Ansatz? Die Frage ist in ihrem gegenwärtigen Zustand zu vage. – estus

+0

Ich habe mehr Markup zum Produktseite Beispiel hinzugefügt. Würde der Produktcontroller alle Daten in einem Service/Modell laden, und die Kinder verwenden das einfach? –

+0

Ich würde einen Service absolut versprechen-basiert, viel flexibler und konsistenter machen. HTTP-Versprechungen von $ werden bei den ersten Anforderungen im Service zwischengespeichert, bei den nächsten Anforderungen zurückgegeben und bei Bedarf erneut validiert. Das Abwickeln eines Service mit dem Status-/Routen-Resolver kann von Vorteil sein, da ein Resolver den Versprechenswert eingibt und es nicht erforderlich ist, ein Versprechen manuell auszupacken. – estus

Antwort

0

Sie können einen Komponentenbaum mit Ihrem Service verwenden. mit einem Designer-Startfreundlich:

<div ng-app="MyApp"> 
    <product id="1"> 
    <product-image></product-image> 
    </product> 
</div> 

So etwas sorta funktioniert:

angular.module('MyApp', []) 

.factory('api', function($q){ 
    return { 
    loadProduct: function(id){ 
     return $q.when({ 
     id: id, 
    imageUrl: 'http://i2.cdn.turner.com/cnnnext/dam/assets/160407085910-setsuna-main-overlay-tease.jpg' 
    }) 
    } 
    }; 
}) 
.component('product', { 
    transclude: true, 
    bindings: { 
    id: '=' 
    }, 
    template: [ 
    '<div ng-transclude></div>' 
    ].join(''), 
    controller: function(api) { 
    var self = this; 
    this.$onInit = function() { 
     self.data = api.loadProduct(this.id); 
    }; 
    } 
}) 
.component('productImage', { 
    require: { 
    product: '^product' 
    }, 
    bindings: { 
    }, 
    template: [ 
    '<pre>{{ $ctrl.url | json }}</pre>' 
    ].join(''), 
    controller: function() { 
    var self = this; 
    this.url = false; 
    this.$onInit = function() { 
     this.product.data.then(function(data){ 
     self.url = data.imageUrl; 
     }) 
    }; 
    } 
}) 

diesen CodePen Siehe: http://codepen.io/anon/pen/wGmEKP?editors=1011

+0

Ich mag diese Lösung, das Problem, das ich sehe, ist jedoch, dass Sie 2-Wege-Bindung mit den übergeordneten Produktdaten verlieren. Wenn Sie beispielsweise angeben, dass Sie Daten in aktualisieren und dann die Produktdaten innerhalb des übermitteln, sind alle Änderungen, die Sie innerhalb von vorgenommen haben, nur innerhalb dieser Richtlinie vorhanden. –

+0

Nicht unbedingt ... Es gibt Möglichkeiten, diese Bereiche verknüpft zu halten ... (Akzeptierte Antwort? Soll ich weiter nachforschen?) – malix

Verwandte Themen