Anwendungsentwicklung mit dem Rapid Application Development Framework AllcountJS

Veröffentlicht: 2022-03-11

Die Idee des Rapid Application Development (RAD) wurde als Antwort auf traditionelle Wasserfall-Entwicklungsmodelle geboren. Es gibt viele Variationen von RAD; zum Beispiel agile Entwicklung und der Rational Unified Process. All diese Modelle haben jedoch eines gemeinsam: Sie zielen darauf ab, durch Prototyping und iterative Entwicklung einen maximalen Geschäftswert mit minimaler Entwicklungszeit zu erzielen. Um dies zu erreichen, stützt sich das Rapid Application Development-Modell auf Tools, die den Prozess vereinfachen. In diesem Artikel werden wir ein solches Tool untersuchen und wie es verwendet werden kann, um sich auf den Geschäftswert und die Optimierung des Entwicklungsprozesses zu konzentrieren.

AllcountJS ist ein aufstrebendes Open-Source-Framework, das mit Blick auf die schnelle Anwendungsentwicklung entwickelt wurde. Es basiert auf der Idee der deklarativen Anwendungsentwicklung unter Verwendung von JSON-ähnlichem Konfigurationscode, der die Struktur und das Verhalten der Anwendung beschreibt. Das Framework wurde auf Node.js, Express, MongoDB aufgebaut und stützt sich stark auf AngularJS und Twitter Bootstrap. Obwohl es auf deklarative Muster angewiesen ist, ermöglicht das Framework bei Bedarf weitere Anpassungen durch direkten Zugriff auf die API.

AllcountJS als Ihr RAD-Framework

Warum AllcountJS als Ihr RAD-Framework?

Laut Wikipedia gibt es mindestens hundert Tools, die eine schnelle Anwendungsentwicklung versprechen, aber da stellt sich die Frage: Wie schnell ist „schnell“. Erlauben diese Tools die Entwicklung einer bestimmten datenzentrischen Anwendung in wenigen Stunden? Oder vielleicht ist es „schnell“, wenn die Anwendung in wenigen Tagen oder Wochen entwickelt werden kann. Einige dieser Tools behaupten sogar, dass es nur wenige Minuten dauert, um eine funktionierende Anwendung zu erstellen. Es ist jedoch unwahrscheinlich, dass Sie eine nützliche Anwendung in weniger als fünf Minuten erstellen und trotzdem behaupten können, alle geschäftlichen Anforderungen erfüllt zu haben. AllcountJS erhebt nicht den Anspruch, ein solches Tool zu sein; Was AllcountJS bietet, ist eine Möglichkeit, in kurzer Zeit einen Prototyp einer Idee zu erstellen.

Mit dem AllcountJS-Framework ist es möglich, mit minimalem Aufwand und Zeit eine Anwendung mit einer themenfähigen, automatisch generierten Benutzeroberfläche, Benutzerverwaltungsfunktionen, einer RESTful-API und einer Handvoll anderer Funktionen zu erstellen. Es ist möglich, AllcountJS für eine Vielzahl von Anwendungsfällen zu verwenden, aber es eignet sich am besten für Anwendungen, bei denen Sie verschiedene Sammlungen von Objekten mit unterschiedlichen Ansichten dafür haben. Typischerweise eignen sich Geschäftsanwendungen gut für dieses Modell.

AllcountJS wurde verwendet, um allcountjs.com zu erstellen, plus einen Projekt-Tracker dafür. Es ist erwähnenswert, dass allcountjs.com eine angepasste AllcountJS-Anwendung ist und dass AllcountJS es ermöglicht, sowohl statische als auch dynamische Ansichten mit wenig Aufwand zu kombinieren. Es ermöglicht sogar das Einfügen dynamisch geladener Teile in statische Inhalte. Beispielsweise verwaltet AllcountJS eine Sammlung von Demoanwendungsvorlagen. Auf der Hauptseite von allcountjs.com gibt es ein Demo-Widget, das eine zufällige Anwendungsvorlage aus dieser Sammlung lädt. Eine Handvoll weiterer Beispielanwendungen sind in der Galerie auf allcountjs.com verfügbar.

Einstieg

Um einige der Fähigkeiten des RAD-Frameworks AllcountJS zu demonstrieren, werden wir eine einfache Anwendung für Toptal erstellen, die wir Toptal Community nennen werden. Wenn Sie unserem Blog folgen, wissen Sie vielleicht bereits, dass eine ähnliche Anwendung mit Hoodie als Teil eines unserer früheren Blogbeiträge erstellt wurde. Diese Anwendung ermöglicht es Community-Mitgliedern, sich anzumelden, Veranstaltungen zu erstellen und sich für die Teilnahme zu bewerben.

Um die Umgebung einzurichten, sollten Sie Node.js, MongoDB und Git installieren. Installieren Sie dann die AllcountJS CLI, indem Sie den Befehl „npm install“ aufrufen und die Projektinitialisierung durchführen:

 npm install -g allcountjs-cli allcountjs init toptal-community-allcount cd toptal-community-allcount npm install

Die AllcountJS-CLI fordert Sie auf, einige Informationen zu Ihrem Projekt einzugeben, um die Datei „package.json“ vorab auszufüllen.

AllcountJS kann als eigenständiger Server oder als Abhängigkeit verwendet werden. In unserem ersten Beispiel werden wir AllcountJS nicht erweitern, daher sollte ein eigenständiger Server für uns funktionieren.

In diesem neu erstellten Verzeichnis app-config ersetzen wir den Inhalt der JavaScript-Datei main.js durch das folgende Code-Snippet:

 A.app({ appName: "Toptal Community", onlyAuthenticated: true, allowSignUp: true, appIcon: "rocket", menuItems: [{ name: "Events", entityTypeId: "Event", icon: "calendar" }, { name: "My Events", entityTypeId: "MyEvent", icon: "calendar" }], entities: function(Fields) { return { Event: { title: "Events", fields: { eventName: Fields.text("Event").required(), date: Fields.date("Date").required(), time: Fields.text("Starts at").masked("99:99").required(), appliedUsers: Fields.relation("Applied users", "AppliedUser", "event") }, referenceName: "eventName", sorting: [['date', -1], ['time', -1]], actions: [{ id: "apply", name: "Apply", actionTarget: 'single-item', perform: function (User, Actions, Crud) { return Crud.actionContextCrud().readEntity(Actions.selectedEntityId()).then(function (eventToApply) { var userEventCrud = Crud.crudForEntityType('UserEvent'); return userEventCrud.find({filtering: {"user": User.id, "event": eventToApply.id}}).then(function (events) { if (events.length) { return Actions.modalResult("Can't apply to event", "You've already applied to this event"); } else { return userEventCrud.createEntity({ user: {id: User.id}, event: {id: eventToApply.id}, date: eventToApply.date, time: eventToApply.time }).then(function () { return Actions.navigateToEntityTypeResult("MyEvent") }); } }); }) } }] }, UserEvent: { fields: { user: Fields.fixedReference("User", "OnlyNameUser").required(), event: Fields.fixedReference("Event", "Event").required(), date: Fields.date("Date").required(), time: Fields.text("Starts at").masked("99:99").required() }, filtering: function (User) { return {"user.id": User.id} }, sorting: [['date', -1], ['time', -1]], views: { MyEvent: { title: "My Events", showInGrid: ['event', 'date', 'time'], permissions: { write: [], delete: null } }, AppliedUser: { permissions: { write: [] }, showInGrid: ['user'] } } }, User: { views: { OnlyNameUser: { permissions: { read: null, write: ['admin'] } }, fields: { username: Fields.text("User name") } } } } } });

Obwohl AllcountJS mit Git-Repositories funktioniert, werden wir es der Einfachheit halber in diesem Tutorial nicht verwenden. Um die Toptal Community-Anwendung auszuführen, müssen wir lediglich den Befehl AllcountJS CLI run im Verzeichnis toptal-community-allcount aufrufen.

 allcountjs run

Es ist erwähnenswert, dass MongoDB ausgeführt werden sollte, wenn dieser Befehl ausgeführt wird. Wenn alles gut geht, sollte die Anwendung unter http://localhost:9080 betriebsbereit sein.

Um sich anzumelden, verwenden Sie bitte den Benutzernamen „admin“ und das Passwort „admin“.

Weniger als 100 Zeilen

Sie haben vielleicht bemerkt, dass die in main.js definierte Anwendung nur 91 Codezeilen benötigte. Diese Zeilen enthalten die Deklaration aller Verhaltensweisen, die Sie möglicherweise beobachten, wenn Sie zu http://localhost:9080 navigieren. Also, was passiert genau unter der Haube? Lassen Sie uns einen genaueren Blick auf jeden Aspekt der Anwendung werfen und sehen, wie sich der Code auf sie bezieht.

Anmelden / Registrieren

Die erste Seite, die Sie nach dem Öffnen der Anwendung sehen, ist eine Anmeldeseite. Diese dient gleichzeitig als Anmeldeseite, vorausgesetzt, dass das Kontrollkästchen mit der Bezeichnung „Anmelden“ aktiviert ist, bevor Sie das Formular absenden.

Anmelden / Registrieren

Diese Seite wird angezeigt, weil die Datei main.js deklariert, dass nur authentifizierte Benutzer diese Anwendung verwenden dürfen. Darüber hinaus ermöglicht es Benutzern, sich von dieser Seite aus anzumelden. Dazu waren nur die folgenden zwei Zeilen nötig:

 A.app({ ..., onlyAuthenticated: true, allowSignUp: true, ... })

Startseite

Nach der Anmeldung werden Sie auf eine Willkommensseite mit einem Anwendungsmenü weitergeleitet. Dieser Teil der Anwendung wird automatisch generiert, basierend auf den Menüpunkten, die unter dem Schlüssel „menuItems“ definiert sind.

Willkommensseite Beispiel

Zusammen mit einigen anderen relevanten Konfigurationen ist das Menü in der Datei main.js wie folgt definiert:

 A.app({ ..., appName: "Toptal Community", appIcon: "rocket", menuItems: [{ name: "Events", entityTypeId: "Event", icon: "calendar" }, { name: "My Events", entityTypeId: "MyEvent", icon: "calendar" }], ... });

AllcountJS verwendet Font Awesome-Symbole, sodass alle Symbolnamen, auf die in der Konfiguration verwiesen wird, Font Awesome-Symbolnamen zugeordnet werden.

Durchsuchen und Bearbeiten von Ereignissen

Nachdem Sie im Menü auf „Ereignisse“ geklickt haben, gelangen Sie zur Ereignisansicht, die im folgenden Screenshot gezeigt wird. Es handelt sich um eine standardmäßige AllcountJS-Ansicht, die einige generische CRUD-Funktionalitäten für die entsprechenden Entitäten bereitstellt. Hier können Sie nach Veranstaltungen suchen, neue Veranstaltungen erstellen und bestehende bearbeiten oder löschen. Es gibt zwei Modi dieser CRUD-Schnittstelle: Liste und Formular. Dieser Teil der Anwendung wird über die folgenden paar Zeilen JavaScript-Code konfiguriert.

 A.app({ ..., entities: function(Fields) { return { Event: { title: "Events", fields: { eventName: Fields.text("Event").required(), date: Fields.date("Date").required(), time: Fields.text("Starts at").masked("99:99").required(), appliedUsers: Fields.relation("Applied users", "AppliedUser", "event") }, referenceName: "eventName", sorting: [['date', -1], ['time', -1]], ... } } } });

Dieses Beispiel zeigt, wie Entitätsbeschreibungen in AllcountJS konfiguriert werden. Beachten Sie, wie wir eine Funktion verwenden, um die Entitäten zu definieren; Jede Eigenschaft der AllcountJS-Konfiguration kann eine Funktion sein. Diese Funktionen können die Auflösung von Abhängigkeiten über ihre Argumentnamen anfordern. Bevor die Funktion aufgerufen wird, werden entsprechende Abhängigkeiten eingefügt. Hier ist „Fields“ eine der AllcountJS-Konfigurations-APIs, die zur Beschreibung von Entitätsfeldern verwendet werden. Die Eigenschaft „Entitäten“ enthält Name-Wert-Paare, wobei der Name eine Entitätstypkennung und der Wert ihre Beschreibung ist. In diesem Beispiel wird ein Entitätstyp für Ereignisse beschrieben, wobei der Titel „Ereignisse“ lautet. Andere Konfigurationen, wie etwa Standard-Sortierreihenfolge, Referenzname und dergleichen, können ebenfalls hier definiert werden. Die Standard-Sortierreihenfolge wird durch ein Array von Feldnamen und Richtungen definiert, während der Referenzname durch eine Zeichenfolge definiert wird (lesen Sie hier mehr).

allcountJS-Funktion

Dieser spezielle Entitätstyp wurde mit vier Feldern definiert: „eventName“, „date“, „time“ und „appliedUsers“, von denen die ersten drei in der Datenbank gespeichert werden. Diese Felder sind Pflichtfelder, wie durch die Verwendung von „erforderlich ()“ angegeben. Werte in diesen Feldern mit solchen Regeln werden validiert, bevor das Formular an das Frontend gesendet wird, wie im folgenden Screenshot gezeigt. AllcountJS kombiniert sowohl clientseitige als auch serverseitige Validierungen, um die beste Benutzererfahrung zu bieten. Das vierte Feld ist eine Beziehung, die eine Liste von Benutzern enthält, die sich für die Teilnahme an der Veranstaltung beworben haben. Dieses Feld wird natürlich nicht in der Datenbank gespeichert und wird ausgefüllt, indem nur die für das Ereignis relevanten AppliedUser-Entitäten ausgewählt werden.

allcountjs Entwicklungsregeln

Bewerbung für die Teilnahme an Veranstaltungen

Wenn ein Benutzer ein bestimmtes Ereignis auswählt, zeigt die Symbolleiste eine Schaltfläche mit der Bezeichnung „Übernehmen“. Ein Klick darauf fügt das Ereignis dem Zeitplan des Benutzers hinzu. In AllcountJS können ähnliche Aktionen konfiguriert werden, indem sie einfach in der Konfiguration deklariert werden:

 actions: [{ id: "apply", name: "Apply", actionTarget: 'single-item', perform: function (User, Actions, Crud) { return Crud.actionContextCrud().readEntity(Actions.selectedEntityId()).then(function (eventToApply) { var userEventCrud = Crud.crudForEntityType('UserEvent'); return userEventCrud.find({filtering: {"user": User.id, "event": eventToApply.id}}).then(function (events) { if (events.length) { return Actions.modalResult("Can't apply to event", "You've already applied to this event"); } else { return userEventCrud.createEntity({ user: {id: User.id}, event: {id: eventToApply.id}, date: eventToApply.date, time: eventToApply.time }).then(function () { return Actions.navigateToEntityTypeResult("MyEvent") }); } }); }) } }]

Die Eigenschaft „Aktionen“ eines beliebigen Entitätstyps nimmt ein Array von Objekten an, die das Verhalten jeder benutzerdefinierten Aktion beschreiben. Jedes Objekt hat eine „id“-Eigenschaft, die eine eindeutige Kennung für die Aktion definiert, die Eigenschaft „name“ definiert den Anzeigenamen und die Eigenschaft „actionTarget“ wird verwendet, um den Aktionskontext zu definieren. Das Setzen von „actionTarget“ auf „single-item“ gibt an, dass die Aktion mit einem bestimmten Ereignis ausgeführt werden soll. Eine unter der Eigenschaft „perform“ definierte Funktion ist die Logik, die ausgeführt wird, wenn diese Aktion ausgeführt wird, typischerweise wenn der Benutzer auf die entsprechende Schaltfläche klickt.

Abhängigkeiten können von dieser Funktion angefordert werden. In diesem Beispiel hängt die Funktion beispielsweise von „Benutzer“, „Aktionen“ und „Crud“ ab. Wenn eine Aktion auftritt, kann ein Verweis auf den Benutzer, der diese Aktion aufruft, erhalten werden, indem die „Benutzer“-Abhängigkeit angefordert wird. Hier wird auch die „Crud“-Abhängigkeit angefordert, die die Manipulation des Datenbankstatus für diese Entitäten ermöglicht. Die beiden Methoden, die eine Instanz des Crud-Objekts zurückgeben, sind: Die Methode „actionContextCrud()“ – gibt CRUD für den Entitätstyp „Event“ zurück, da die Aktion „Apply“ dazu gehört, während die Methode „crudForEntityType()“ – CRUD zurückgibt für jeden Entitätstyp, der durch seine Typ-ID identifiziert wird.

CRUD-Abhängigkeiten

Die Implementierung der Aktion beginnt mit der Überprüfung, ob dieses Ereignis bereits für den Benutzer geplant ist, und wenn nicht, wird eines erstellt. Wenn es bereits geplant ist, wird ein Dialogfeld angezeigt, in dem der Wert aus dem Aufruf von „Actions.modalResult()“ zurückgegeben wird. Neben dem Anzeigen eines Modals kann eine Aktion verschiedene Arten von Vorgängen auf ähnliche Weise ausführen, z. B. „Zur Ansicht navigieren“, „Ansicht aktualisieren“, „Dialog anzeigen“ und so weiter.

Durchführung der Aktion

Benutzerzeitplan der angewendeten Ereignisse

Nach erfolgreicher Bewerbung für eine Veranstaltung wird der Browser zur Ansicht „Meine Veranstaltungen“ umgeleitet, die eine Liste der Veranstaltungen anzeigt, für die sich der Benutzer beworben hat. Die Ansicht wird durch die folgende Konfiguration definiert:

 UserEvent: { fields: { user: Fields.fixedReference("User", "OnlyNameUser").required(), event: Fields.fixedReference("Event", "Event").required(), date: Fields.date("Date").required(), time: Fields.text("Starts at").masked("99:99").required() }, filtering: function (User) { return {"user.id": User.id} }, sorting: [['date', -1], ['time', -1]], views: { MyEvent: { title: "My Events", showInGrid: ['event', 'date', 'time'], permissions: { write: [], delete: null } }, AppliedUser: { permissions: { write: [] }, showInGrid: ['user'] } } },

In diesem Fall verwenden wir eine neue Konfigurationseigenschaft, „filtering“. Wie bei unserem vorherigen Beispiel ist auch diese Funktion auf die Abhängigkeit „Benutzer“ angewiesen. Wenn die Funktion ein Objekt zurückgibt, wird es als MongoDB-Abfrage behandelt; Die Abfrage filtert die Sammlung nach Ereignissen, die nur dem aktuellen Benutzer gehören.

Eine weitere interessante Eigenschaft ist „Ansichten“. „View“ ist ein regulärer Entitätstyp, aber seine MongoDB-Sammlung ist die gleiche wie für den übergeordneten Entitätstyp. Dadurch ist es möglich, visuell unterschiedliche Ansichten für dieselben Daten in der Datenbank zu erstellen. Tatsächlich haben wir diese Funktion verwendet, um zwei verschiedene Ansichten für „UserEvent“ zu erstellen: „MyEvent“ und „AppliedUser“. Da der Prototyp der Unteransichten auf den übergeordneten Entitätstyp festgelegt ist, werden Eigenschaften, die nicht überschrieben werden, vom übergeordneten Typ „geerbt“.

Ansichten

Veranstaltungsteilnehmer auflisten

Nachdem Sie sich für eine Veranstaltung beworben haben, sehen andere Benutzer möglicherweise eine Liste aller Benutzer, die daran teilnehmen möchten. Diese wird als Ergebnis der folgenden Konfigurationselemente in main.js generiert:

 AppliedUser: { permissions: { write: [] }, showInGrid: ['user'] } // ... appliedUsers: Fields.relation("Applied users", "AppliedUser", "event")

„AppliedUser“ ist eine schreibgeschützte Ansicht für den Entitätstyp „MyEvent“. Diese Nur-Lese-Berechtigung wird erzwungen, indem ein leeres Array auf die „Write“-Eigenschaft des Berechtigungsobjekts gesetzt wird. Da die Berechtigung „Lesen“ nicht definiert ist, ist das Lesen standardmäßig allen Benutzern gestattet.

angewandter Benutzer für meinen Ereignistyp

Standardimplementierungen erweitern

Der typische Nachteil von RAD-Frameworks ist der Mangel an Flexibilität. Sobald Sie Ihre App erstellt haben und sie anpassen müssen, stoßen Sie möglicherweise auf erhebliche Hindernisse. AllcountJS wurde im Hinblick auf Erweiterbarkeit entwickelt und ermöglicht den Austausch aller darin enthaltenen Bausteine.

Um dies zu erreichen, verwendet AllcountJS seine eigene Dependency Injection (DI)-Implementierung. DI ermöglicht es dem Entwickler, das Standardverhalten des Frameworks durch Erweiterungspunkte zu überschreiben, und ermöglicht es gleichzeitig durch die Wiederverwendung bestehender Implementierungen. Viele Aspekte der RAD-Framework-Erweiterung werden in den Dokumentationen beschrieben. In diesem Abschnitt werden wir untersuchen, wie wir zwei der vielen Komponenten im Framework erweitern können, serverseitige Logik und Ansichten.

Lassen Sie uns in unserem Toptal-Community-Beispiel eine externe Datenquelle integrieren, um Ereignisdaten zu aggregieren. Stellen wir uns vor, es gibt Toptal-Blog-Beiträge, in denen Pläne für Veranstaltungen am Tag vor jeder Veranstaltung diskutiert werden. Mit Node.js soll es möglich sein, den RSS-Feed des Blogs zu parsen und solche Daten zu extrahieren. Dazu benötigen wir einige zusätzliche npm-Abhängigkeiten, wie „request“, „xml2js“ (um den RSS-Feed des Toptal-Blogs zu laden), „q“ (um Promises zu implementieren) und „moment“ (um Daten zu analysieren). Diese Abhängigkeiten können durch Aufrufen des folgenden Befehlssatzes installiert werden:

 npm install xml2js npm install request npm install q npm install moment

Erstellen wir eine weitere JavaScript-Datei, nennen Sie sie „toptal-community.js“ im Verzeichnis „toptal-community-allcount“ und füllen Sie sie mit Folgendem:

 var request = require('request'); var Q = require('q'); var xml2js = require('xml2js'); var moment = require('moment'); var injection = require('allcountjs'); injection.bindFactory('port', 9080); injection.bindFactory('dbUrl', 'mongodb://localhost:27017/toptal-community'); injection.bindFactory('gitRepoUrl', 'app-config'); injection.bindFactory('DiscussionEventsImport', function (Crud) { return { importEvents: function () { return Q.nfcall(request, "https://www.toptal.com/blog.rss").then(function (responseAndBody) { var body = responseAndBody[1]; return Q.nfcall(xml2js.parseString, body).then (function (feed) { var events = feed.rss.channel[0].item.map(function (item) { return { eventName: "Discussion of " + item.title, date: moment(item.pubDate, "DD MMM YYYY").add(1, 'day').toDate(), time: "12:00" }}); var crud = Crud.crudForEntityType('Event'); return Q.all(events.map(function (event) { return crud.find({query: {eventName: event.eventName}}).then(function (createdEvent) { if (!createdEvent[0]) { return crud.createEntity(event); } }); } )); }); }) } }; }); var server = injection.inject('allcountServerStartup'); server.startup(function (errors) { if (errors) { throw new Error(errors.join('\n')); } });

In dieser Datei definieren wir eine Abhängigkeit namens „DiscussionEventsImport“, die wir in unserer main.js-Datei verwenden können, indem wir eine Importaktion für den Entitätstyp „Event“ hinzufügen.

 { id: "import-blog-events", name: "Import Blog Events", actionTarget: "all-items", perform: function (DiscussionEventsImport, Actions) { return DiscussionEventsImport.importEvents().then(function () { return Actions.refreshResult() }); } }

Da es wichtig ist, den Server neu zu starten, nachdem Sie einige Änderungen an den JavaScript-Dateien vorgenommen haben, können Sie die vorherige Instanz beenden und erneut starten, indem Sie denselben Befehl wie zuvor ausführen:

 node toptal-community.js

Wenn alles gut geht, sehen Sie nach dem Ausführen der Aktion „Blog-Ereignisse importieren“ so etwas wie den folgenden Screenshot.

Aktion „Blog-Ereignisse importieren“.

So weit so gut, aber lassen Sie uns hier nicht aufhören. Standardansichten funktionieren, aber sie können manchmal langweilig sein. Lassen Sie uns sie ein wenig anpassen.

Magst du Karten? Jeder mag Karten! Um eine Kartenansicht zu erstellen, fügen Sie Folgendes in eine Datei namens events.jade im Verzeichnis app-config ein:

 extends main include mixins block vars - var hasToolbar = true block content .refresh-form-controller(ng-app='allcount', ng-controller='EntityViewController') +defaultToolbar() .container.screen-container(ng-cloak) +defaultList() .row: .col-lg-4.col-md-6.col-xs-12(ng-repeat="item in items") .panel.panel-default .panel-heading h3 {{item.date | date}} {{item.time}} div button.btn.btn-default.btn-xs(ng-if="!isInEditMode", lc-tooltip="View", ng-click="navigate(item.id)"): i.glyphicon.glyphicon-chevron-right |   button.btn.btn-danger.btn-xs(ng-if="isInEditMode", lc-tooltip="Delete", ng-click="deleteEntity(item)"): i.glyphicon.glyphicon-trash .panel-body h3 {{item.eventName}} +noEntries() +defaultEditAndCreateForms() block js +entityJs()

Verweisen Sie danach einfach von der Entität „Event“ in main.js als „customView: „events““. Führen Sie Ihre App aus und Sie sollten eine kartenbasierte Schnittstelle anstelle der standardmäßigen tabellarischen sehen.

Ereignisentität in main.js

Fazit

Heutzutage ist der Entwicklungsfluss von Webanwendungen für viele Webtechnologien ähnlich, wobei einige Vorgänge immer wieder wiederholt werden. Lohnt es sich wirklich? Vielleicht ist es an der Zeit, die Art und Weise, wie Ihre Webanwendungen entwickelt werden, zu überdenken?

AllcountJS bietet einen alternativen Ansatz zu Frameworks für die schnelle Anwendungsentwicklung; Sie beginnen mit der Erstellung eines Skeletts für die Anwendung, indem Sie Entitätsbeschreibungen definieren, und fügen dann Ansichten und Verhaltensanpassungen darum herum hinzu. Wie Sie sehen können, haben wir mit AllcountJS eine einfache, aber voll funktionsfähige Anwendung in weniger als hundert Zeilen Code erstellt. Vielleicht erfüllt es nicht alle Produktionsanforderungen, aber es ist anpassbar. All dies macht AllcountJS zu einem guten Werkzeug für das schnelle Bootstrapping von Webanwendungen.