Je voulais dire un fichier app-routing.module, qui gère les routes au niveau app. Du genre si tu as un menu de navigation dans la page d'accueil, tu aurais une première définition des routes pour ce menu : je clique tel item, j'affiche tel component/module.
Et effectivement, dans le module affichéensuite, tu peux également avoir d'autres routes.
Mais déjà, un fichier de routes au niveau app, permettra de gérer un menu de navigation basique.
Je viens de vérifier et en fait tu peux aussi générer les fichiers de route : https://github.com/angular/angular-c...ies/routing.md
Tout a fait ce que je cherchais oui.
Je vois que de base, il ajoute Path ET Children en même temps. Je ne vois pas dans quel cas il est préférable d'utiliser dans le route parent plutôt que de faire une route directement dans le module correspondant au path. Les deux me semblent tout aussi viable. Passer par le route de l'enfant me semblant plus pérenne à première vue, puisqu'on évitera d'avoir 50 routes dans le même fichier.
Pour décider si on fait plutôt un module ou un component : on se demande si on va réutiliser se component ailleurs?
Dans mon exemple de sites avec des articles, à priori, ça ne serait affiché qu'a un seul endroit, donc je pourrait directement rattaché le component à app module? Ou bien est ce toujours une bonne pratique de créer un module et de lui ajouter un composant, même si ce module ne contient qu'un seul composant?
De la, j'exporte le composant via le module, et je ré importe le composant (ou le module?) dans mon app module?
Au final, il serait tout à fait possible d'avoir une app composé uniquement de modules uni component par exemple :
un module avec composant 'formulaire de contact'
un module avec un composant 'liste d'articles'
un module avec un composant 'présentation'
Chacun des composants cité n'étant nécessaire ailleurs. Dans un premier temps. Puisque, évidemment, on pourrait décider d'afficher un formulaire de contact en bas du composants de présentation par exemple.
Tout cela est bien sur dans l'hypothétique, j’essaie de dégrossir un peu le fonctionnement global d'une app angular.
Dernière modification par Dynames ; 24/08/2017 à 16h01.
Les modules ne servent pas qu'à déclarer des éléments réutilisables mais à aussi organiser proprement ton application.
Dans une app Angular, tu vas trouver généralement ces modules :
- AppModule => obligatoire, sert au boostrap de l'application :
- Importe les modules devant être initialisés au niveau root (AppRoutingModule, BrowserModule, BrowserAnimationModule, les modules instanciant des singletons, etc) + les modules de n'utilisant pas le lazyloading
- Ne déclare quasiment jamais de component dedans (sauf AppComponent bien sur)
- Ne déclare pas de provider généralement (sauf dans le cas où on veut remplacer l'instance d'un service d'une librairie par un service custom, par exemple pour override le service Http d'Angular)
- N'exporte rien
- N'est importé nulle part (normal pour le module root )
- Déclare uniquement les routes de base (404, login, redirection + le premier élément des routes métier)
- CoreModule => dédié aux singletons :
- Importe le SharedModule
- Ne déclare quasiment jamais de component, sauf ceux utilisés une seul
- Déclare en provider tous les services que tu veux utiliser en singleton à plusieurs endroits dans ton appli
- N'exporte généralement rien (sauf component qu'on voudrait utiliser dans le AppComponent)
- Est importé dans le AppModule uniquement
- Ne déclare par de routes
- SharedMoule => permet de regrouper les modules et les components partagés par les différents modules de ton app
- Importe les modules que tu utilises partout (CommonModule, HttpModule, FormsModule, RouterModule, etc) => ceci permet de devoir dupliquer ces imports un peu partout
- Déclare les components que tu vas utiliser à plusieurs endroits (par exemple une card ou un input custom)
- Ne déclare généralement aucun provider
- Export tous les modules importés + les components que tu utilises ailleurs
- Est importé dans quasiment tous les modules sauf AppModule
- Ne déclare par de routes
- Le(s) module(s) métier => généralement tu vas créer un gros module pour chaque route/partie de ton application (correspondant généralement à un onglet de ta navbar)
- Importe le SharedModule
- Déclare les components spécifiques à cette partie de l'application
- Déclare en provider les "singleton locaux" (services spécifiques à cette partie de l'application mais agissant comme des singletons)
- N'exporte généralement rien
- Est soit importé par le AppModule (pas de LazyLoading), soit déclaré dans les routes du AppModule (LazyLoading)
- Déclare les routes qui lui sont propre
Après, lorsque ton application commence à grossir, tu peux faire un découpage un peu plus fin pour garder le tout propre.
Et tu peux aussi utiliser les modules pour certains cas spécifiques : pour une application sur laquelle je travaille actuellement il y a toute une partie de l'application qui est utilisée à 2 endroits de l'arborescence, mais pas au même niveau (dans un c'est inclus derrière par mal de route et à l'intérieur de components).
Du coup j'ai un module dédié à ces fonctionnalités là que j'injecte dans les routes aux 2 endroits voulus.
Je vois, je vais essayer de me construire quelque chose basé la dessus.
J'ai eu un cas avec cette structure, ou je mettais le module dans la route au niveau app de cette manière.
Derrière, j'ai voulu charger SharedModule dans ArticleModule :Code:path: articles, loadChildren: 'app/article/article.module#ArticleModule' qui est si je ne me trompe pas, le lazyloading dont tu parlais.Comme ça, j'obtiens une erreur 'Maximum call stack' qui semble être lié au fait de faire du chargement de module en boucle.Code:imports: [ArticleRoutingModule, SharedModule]
Je me soupçonne d'avoir oublié un détail dans les imports/exports au niveau de ma structure. Je pense que ma structure de base est pas encore tout à fait clean, mais j'avais l’impression qu'ua niveau import/export, ça semblait bon, je me trompais.
J'ai mis ça sur git hub (avec l'erreur) : https://github.com/kme-rennes/dev-site-as-with-angular
Pour le moment, je n'ai que la structure de base et j'attaquerais l'ajout des composants pour mes modules métiers après.
T'es sur d'avoir bien commit (ou de ne pas travailler sur une branche uniquement locale) ? Sur ton repo la dernière modification est vieille de 7 jours.
C'est que je bosse sur VM, et pour pouvoir utilisé certains outils sur cette VM, je dois reculer la date pour pigeonner les versions d'éval (j'étais d'ailleurs étonné que ça fonctionne, quelque chose d'aussi basique, et que ensuite, git hub ne se protège pas contre ça avec une erreur FUTURE_Response). Donc c'est marqué 7 jours, mais en fait c'était fait tout à l'heure (d'ailleurs, le compte est aussi de ce matin). Et je préfère bosser sur VM, au cas ou un des outils que j'installerais, ferait beaucoup(trop) de changements dans le système.
Ton erreur vient des imports de ton SharedModule : CommonModule, FormsModule, BrowserModule, AppRoutingModule
Seuls CommonModule et FormsModule devraient être importés.
BrowserModule doit être importés dans le module root (rien à voir avec ton erreur, mais faut aussi corriger ça).
L'import de AppRoutingModule est celui qui cause la boucle infinie (et donc l'erreur "Maximum call stack") vu que lorsque tu charges ArticleModule tu as la chaine d'import suivante qui se créée : ArticleModule => SharedModule => AppRoutingModule => ArticleModule
Je vois, effectivement, c'était bien ça.
Du coup, j'avais mis import et export du AppRoutingModule dans Shared. J'imagine que même si l'avoir dans export(AppRoutingModule) ne génère pas d'erreur, il n'est pas nécessaire, puisqu'il s'agit des routes du AppModule. Puisque lorsque je serais ailleurs que dans le Root, j'aurais les routes dédiées au module?
Sauf si vraiment, j'en ai besoin dans un contexte particulier (mais ce n'est pas le cas actuellement).
Oui, les fichiers de route ne sont pas à exporter, seulement à importer dans le module qui leur est propre.
Hello,
Cette discussion sur angular 4+ tombe à pic.
Je suis en train de m'auto-former sur ce framework.
J'ai fait le tuto 'tours of heroes', puis commencé un peu à bidouiller le truc; ajouter des routes avec des guard etc....
J'ai aussi lu le style guide qui explique comment structurer ses fichiers, les normes de nommage à respecter pour que l'ensemble du projet reste clair.
Je rencontre la même problématique que je me retrouve avec énormément d'import et de déclarations dans mon app.module.ts.
Orhin par rapport à ton message http://forum.canardpc.com/threads/72...1#post11101685 est-ce que tu aurais un exemple d’arborescence sur github par exemple.
Sous la main non, mais je regarderais lundi au taf si je peux exporter quelque chose de mon projet actuel.
Ca me dit bien aussi.
Je n'arrive pas à charger comme il faut mes modules métiers.
J'ai bien ajouté un item dans ma nav, un item dans mon app route (en lazy).
Lorsque je clique sur mon item de nav, l'url ne change pas, et surtout il me parle du component de l'autre item de la nav (j'ai re vérifié, ce component n'est pas appelé par le nouveau module). Y'a un truc qui a du m'échapper das la structure de l'app et la navigation. Je n'arrive pas à voir quoi, et les messages d'erreur n'étant pas toujours très explicite... EN l'occurence il me dit que le component (qui est appelé alors qu'il ne devrait pas) ne fait pas parti d'un NGModule. J'ai mis mon git à jour (attention toujours au 9days ago, basé sur la date de ma VM).
@Paulboy, Mayalabielle : je connaissais Docker en effet. Je croyais que ça répondait plus à une problématique infra. Je testerais, après pour mon cas, ça ne collera pas puisque je dois bidouiller pour la date de ma machine, pour faire tourner les logiciels avec des dates de fins.
edit : trouvé mon problème grace à SO : dans mon SHared, j'exportais mon Routing Module, alors qu'il ne le fallait pas.
Au final, la plus grosse difficulté rencontré avec Angular (et le html5+framwork) c'est le débug. Et avec tous ces fichiers compilé, difficile de retrouver le bon dans la liste pour y mettre un point d'arrêt. La j'ai fait mon service avec mon json. Je n'ai pas d'erreur, mais aucune données affichées : est ce que ça vient du json (mal formaté) de mon html, de mon component? Aucune idée: je ne trouve même pas mon fichier component dans le debugger du navigateur.
Need coup de main sur la partie service/component.
J'ai bien fait mon service en promise, mon ngFor qui va bien, mais ça fonctinne pas.
Pas mal d'exemples sur le net pour écrire ses services, mais on a surtout droit à un mélange de tout, et ça m'embrouille pas mal au final.
Avoir un bon exemple, bien concret pour ma situation ça aiderait franchement (la difficulté ici c'est que je ne sais pas si les exemples trouvés sur le net sont fiables/applicables pour moi)
Dernière modification par Dynames ; 30/08/2017 à 14h12.
Bon sinon, je vais pas pouvoir exporter d'exemple simplement à partir de mon projet.
Par contre je peux regarder vos projets sur Github si besoin.
Pour le debug dans le navigateur, utilisez l'extension pour Chrome Augury : https://augury.angular.io/
Ça permet de voir l'arbre des components et de routing, le contenu des modules (export, imports, etc), l'état et les variables des components.
edit : je viens de regarder sur ton repo Dynames, et t'as pas commit les nouveaux fichiers du projets, ça va être compliqué de t'aider là.
edit2 : en fait ton problème vient de ton *ngFor dans le template de ton component :
Tu utilises un pipe async alors que articles est de type Article[].Code:*ngFor="let article of (articles | async)"
Or ce pipe ne sert que pour les observables, pour créer une souscription locale.
Du coup dans ton cas tu as juste besoin de faire :
Code:*ngFor="let article of articles"
Dernière modification par Orhin ; 31/08/2017 à 10h00.
Ouais, je voyais ça. Mais j'essayais de rester en async.
Du coup je suis passé avec les Observable de Rx JS. Même si toutes les méthodes ont pas l'air de toutes fonctionnées (le take, par exemple, ou alors j'ai mal compris sa définition). Du coup ma pagination ne fonctionne toujours pas comme il faut. Et la doc est pas comète sur tout son contenu. Je commence à douter de cette librairie.
D'un côté je vois du : " il faut privilégier Observable", mais il semble qu'il n'y ai pas moyen de convertir un Observable<Object[]> en Object[]. Ce qui me semble assez surprenant.
EN fait, je ne comprends pas comment ça peut être aussi galère de faire une simple pagination, alors qu'Angular est présenté comme un outil super puissant.
Alors que je vais juste chercher des données dans un json pour en faire un tableau. Et avec les deux méthodes que j'ai vu (Promise et Observable) pour chercher les données de JSON, tu galère pour en faire quelques choses.
Peut être que ce n'est pas forcément fait pour être appris en autonomie (tout seul sans connaisseur à porté de voix).
Merci pour l'extension, je testerais.
Faut pas confondre le principe d'être au maximum en asynchrone et le pipe "async" qui a un usage spécifique.
T'es sur la bonne doc ? Celle officielle de la dernière version (5+, y'a eu de gros changement depuis la 4) c'est là : http://reactivex.io/rxjs/
L'opérateur "take" est assez simple à comprendre : ça prend les X premiers objet de ton flux.
Par exemple si tu as un observable qui contient la séquence "A - B - C - D" et que tu lui adjoint "take(2)" ça va te renvoyer un observable contenant "A - B".
L'erreur que tu fais dans l'utilisation c'est de confondre les articles de ton tableau avec les objet du flux (et donc d'utiliser les méthodes skip et take pour filtrer le tableau).
Dans mon exemple au dessus, A/B/C/D sont chacun des tableau d'article.
Bah c'est normal que tu ne puisses pas convertir un flux d'objet en un objet, vu que d'un côté c'est asynchrone alors que de l'autre c'est synchrone.
On va reprendre point par point :
1) Tu veux afficher dans un tableau une liste d'articles qui vient d'un service te renvoyant les données de façon synchrone :
2) Le service te renvoie les données de façon asynchrone (car appel vers un WS par exemple) via un observable, pour ça tu as 2 solutions équivalentes :Code:// Component articles: Article[]; ngOnInit() { this.articles = this.articleService.getArticles(); } // Template *ngFor="let article of articles"
Code:// Component articles: Article[]; ngOnInit() { this.articleService.getArticles() .subscribe(articles => { this.articles = articles; }): } // Template *ngFor="let article of articles"Dans le premier cas, la souscription à l'observable est faite explicitement dans le component, alors que dans le second cas elle est réalisée par le pipe async dans le template.Code:// Component articles: Observable<Article[]>; ngOnInit() { this.articles = this.articleService.getArticles(); } // Template *ngFor="let article of articles | async"
L'intérêt dans les 2 cas, c'est que si les données contenue dans ton service changent, alors celles affichées seront automatiquement mise à jour grâce à cette souscription à l'observable.
3) Tu veux filtrer les données affichées :
Il est toujours possible d'utiliser l'autre solution avec la souscription explicite, mais par soucis de concision je ne vais plus l'afficher pour la suite, de toute façon elle est facile à deviner.Code:// Component articles: Observable<Article[]>; itemPerPage: 5; page: 1; ngOnInit() { this.articles = this.articleService.getArticles() .map(articles => { return articles.slice((this.page - 1) * this.itemPerPage, this.page * this.itemPerPage); }); } // Template *ngFor="let article of articles | async"
4) Tu veux filtrer les données affichées de façon dynamique (ce qui correspond à ton cas d'usage) :
Ici, j'utilise Observable.combineLatest qui permet de combiner plusieurs observable en un seul qui émet une valeur dès que l'un des observable en émet une.Code:// Component articles: Observable<Article[]>; itemPerPage: 5; initialPage: 1; page: Subject<number> = new Subject<number>(); ngOnInit() { this.articles = Observable.combineLatest( this.articleService.getArticles(), this.page, (articles, page) => { return articles.slice((page - 1) * this.itemPerPage, page * this.itemPerPage); } ); } // Template *ngFor="let article of articles | async" <ngb-pagination (pageChange)="page.next($event)" [pageSize]="itemPerPage" [page]="initialPage"></ngb-pagination>
Par exemple : si j'ai ces 2 séquences
A - - - B - C- -
- - D - - - - - E
alors la séquence de l'observable obtenue sera
[A, D] - [B, D] - [C, D] - [C, E]
Vu qu'on a pas envie de forcément récupérer sous forme brute les valeurs des différents observable source, on peut passer une fonction de composition en dernier argument de combineLatest.
Dans notre cas, cette fonction renvoie la liste d'article filtrée avec la pagination voulue.
Par contre, combineLatest ne prend que des Observable et des Subject en entrée.
La différence entre les 2 c'est qu'un observable ne donne accès qu'à un bout du flux (la sortie via subscribe()) alors que le Subject donne accès aux 2 (sortie via subscribe() et entrée via next()).
Du coup on transforme notre variable "page" en Subject contenant le flux des pages choisies par l'utilisateur.
Ce flux est alimentée grâce à l'output (pageChange) du component ngb-pagination, à chaque nouvelle valeur de l'outpout, on la transfmée à notre Subject "page".
Ça peut paraître un peu verbeux ais derrière ça simplifie la vie dès qu'on passe à ces cas plus complexes.
Par exemple, dans l'exemple précédent on actualise les données à chaque clic utilisateur sur la pagination.
Sauf que si au lieu de faire un simple slice sur ton tableau d'Article tu réalises une opération lourde, tu veux peut être limiter sa fréquence d'exécution pour éviter que le navigateur de l'utilisateur consomme trop de ressources et freeze.
Pour limiter le nombre d'actualisation liée à l'input utilisateur il suffit d'ajouter debounceTime() dans la chaine d'observable :
Ainsi, au lieu d'avoir dans le combineLatest un subject contenant tous les changements de page générés par l'utilisateur, on a un observable qui contient au maximum un changement toutes les 100ms (le dernier est conservé).Code:ngOnInit() { this.articles = Observable.combineLatest( this.articleService.getArticles(), this.page.debounceTime(100), (articles, page) => { return articles.slice((page - 1) * this.itemPerPage, page * this.itemPerPage); } ); }
Dernière modification par Orhin ; 31/08/2017 à 17h12. Motif: correction typo
Effectivement, c'est la que j'avais mal compris les méthodes.L'erreur que tu fais dans l'utilisation c'est de confondre les articles de ton tableau avec les objet du flux (et donc d'utiliser les méthodes skip et take pour filtrer le tableau).
En regardant ton code, ça ressemble pas mal avec ce que j'avais pu testé, mais sans que je puisse le remttre en ordre de marche.
une interrogations sur le code que tu as écris :
j'ai une erreur qui me dit que le côté gauche d'une éval arithmétique ( donc le (articles, pages) => ) doit être number, any ou enum. Je ne connaissais pas du tout le type Subject mais ça semble ne pas convenir pour ce genre de méthode, ou alors il me manquerait un import (Subject étant bien importé)?
Ah mon avis l'erreur provient plutôt d'un "this.page" que tu aurais oublié de transformé en "page" dans :
this.page est un Subject<number>, ce qui est équivalent à un Observable<number>, donc un flux de nombre.Code:articles.slice((page - 1) * this.itemPerPage, page * this.itemPerPage);
Dans le code au dessus, "page" fait référence à un des valeur de ce flux.
edit : il y a une erreur dans le combineLatest, j'ai écris "this.pageChange" alors qu'il faut écrire "this.page".
Effectivement c'était bien ça.
Comment tu ferais, pour avoir une initialisation de la pagination 'dynamique'.
Actuellement déjà, premier point, même si c'est la première page qui est affichée, la liste est vide. De plus, j'ai ajouter unavant le return dans le OnInit, pour avoir le bon nombre de page.Code:itemPerPage = Object.keys(articles).lenght
Mais au premier affichage le nombre de page nest pas bon, et la première page affichée est vide, comme si je n’étais pas passé dans ce code
Une fois que j'ai cliqué au moins une fois sur le pager, tout est ok, mais ce init m'étonne tout de même un peu. Sachant que c'est du init, donc devrait être fait lors du premier affichage.Code:(articles, page) => { return articles.slice((page - 1) * this.itemPerPage, page * this.itemPerPage); }
Dernière modification par Dynames ; 04/09/2017 à 09h59.
Ah oui petit oubli de ma part, le Subject "page" ne contient aucune valeur au départ (car l'output (pageChange) de <ngb-pagination> n'est appelé que lorsque la pagination change, pas à l'initialisation).
Du coup ton Observable.combineLatest(...) ne renvoie rien car il faut au minimum une valeur dans chaque flux que tu combines.
Il faut donc que tu ajoutes dans ton ngOnInit() (avant ou après le combineLatest, peu importe vu que c'est asynchrone) :
Autre solution si tu ne veux pas "polluer" ton Subject avec des valeurs ne provenant pas des interactions utilisateur (ce qui peut être utile si tu l'utilises ailleurs) :Code:this.page.next(this.initialPage)
L'opérateur "startWith" renvoie un Observable/Subject contenant le flux initial + une valeur ajoutée au début.Code:ngOnInit() { this.articles = Observable.combineLatest( this.articleService.getArticles(), this.page.startWith(this.initialPage), (articles, page) => { return articles.slice((page - 1) * this.itemPerPage, page * this.itemPerPage); } ); }
Aucune des deux options ne semblent fonctionnées (j'avais choisi la deuxième au début pour une question d'uniformité avec l'init). En fait il semblerait qu'il ne considère pas le fait de définir l'initial page comme un événement, et donc ne traite pas les données au moment du init mais que plus tard.
edit : je viens de commit avec les modif dont tu m'a parlé, au cas ou j'aurais oublié un détail.
Hum, j'utilise déjà VueJS et je le trouve assez complet, du coup j'ai un peu du mal à voir le scope de https://nuxtjs.org/. Des avis ?
Edit : c'est hum, on dirait que c'est server-side, cette histoire.
"Nobody exists on purpose. Nobody belongs anywhere. We're all going to die. Come watch TV." - Morty Smith
@Mayalabielle : en parcourant vite fait la doc, ça m'a l'air d'être "simplement" une extension de Vue.js pour permettre du rendu côté serveur (au lieu de rendu dynamique dans le navigateur).
Un peu à la manière de https://universal.angular.io/ pour Angular.
Il y a un problème sur la façon dont tu as intégré cette modification :
De la façon dont tu as écris ça, tu fais un combineLatest sur 3 flux différents (au lieu des 2 initiaux).Code:this.articles = Observable.combineLatest( this.articleService.getArticles(), this.page.debounceTime(100), this.page.startWith(this.initialPage), (articles, page) => { this.totalItems = Object.keys(articles).length; return articles.slice((page - 1) * this.itemPerPage, page * this.itemPerPage); } ); }
Or le 2ème flux (this.page.debounceTime(100)) est vide initialement.
Si tu veux utiliser les 2 opérateurs (debounceTime et startWith) sur ton Subject, il suffit d'écrire :
Code:this.articles = Observable.combineLatest( this.articleService.getArticles(), this.page.startWith(this.initialPage).debounceTime(100), (articles, page) => { this.totalItems = Object.keys(articles).length; return articles.slice((page - 1) * this.itemPerPage, page * this.itemPerPage); } ); }
Effectivement, ça fonctionne mieux si on utilise les opérateurs l'un après l'autre, et pas dans deux paramètres différents.
Merci pour le coup de main, avec ça j'ai quelque chose qui tourne avec pas mal des concepts dont j'aurais besoin (reste encore la partie formulaire avec création et édition), ça me permettra de pas mal avancé.
En fin de compte, j'ai bien des difficultés avec les get et create...
Sur le get, il me semble faire ce qu'il faut, mais ça n'a pas l'air de fonctionner et ne charge pas l'item correspondant à l'id.
Pour le create(et delete aussi mais sans doute même problème), je n'arrive pas à passer du promise au Observable.
Au final, le Observable semble intéressant, mais en debug, je n'arrive pas à trouver l'objet lié à l'observable.
Quand j'ai une méthode qui s'appelle Create et renvoi un Observable<Object>, au final, je n'arrive pas à retrouvé l'objet en question et la manipulé. Et moi qui suit habitué au .Net... J'ai l'impression finalement, qu'on complexifie la manipulation d'objet.
Dernière modification par Dynames ; 05/09/2017 à 10h29.
Je viens de regarder ce que tu as commit et tu as plusieurs soucis :
1) tu n'as pas complètement compris comment fonctionne les Observable.
Lorsque tu fais ça :
Absolument rien ne va se passer car tu n'as pas souscris à l'observable renvoyé par la méthode createArticle() de articleService.Code:createArticle(article: Article): void { this.articleService.createArticle(article) .map(articles => { this.articles.push(articles); this.selectedArticle = null; }); }
Il faut que tu fasse :
(idem pour deleteArticle)Code:createArticle(article: Article): void { this.articleService.createArticle(article) .subscribe(articles => { this.articles.push(articles); this.selectedArticle = null; }); }
2) Tu modifies incorrectement "this.articles".
Ce n'est pas un tableau mais un observable.
Tu ne peux pas faire "this.articles.push(articles)".
3) Ce n'est pas le rôle de ton component de modifier la liste des données (this.articles), c'est le rôle de ton service.
Dans ton component, ta méthode createArticle ne devrait contenir que :
(idem pour deleteArticle)Code:createArticle(article: Article): void { this.articleService.createArticle(article) .subscribe(articles => { this.selectedArticle = null; }); }
Tu as déjà cette partie là qui se charge de récupérer la liste des articles depuis ton service :
C'est donc à la méthode getArticles() de articleService de te renvoyer la liste mise à jour après chaque opération de CRUD.Code:this.articles = Observable.combineLatest( this.articleService.getArticles(), this.page.startWith(this.initialPage).debounceTime(100), (articles, page) => { this.totalItems = Object.keys(articles).length; return articles.slice((page - 1) * this.itemPerPage, page * this.itemPerPage); } );
J'ai fait
Pour cela on va modifier ton service :
Spoiler Alert!
Ainsi que ton component liste :
Spoiler Alert!
Et ton component détail :
Spoiler Alert!