Crunchez vos adresses URL
|
Rejoignez notre discord
|
Hébergez vos photos
Page 177 sur 310 PremièrePremière ... 77127167169170171172173174175176177178179180181182183184185187227277 ... DernièreDernière
Affichage des résultats 5 281 à 5 310 sur 9277
  1. #5281
    Citation Envoyé par tenshu Voir le message
    Ca n'en est pas moins intéressant sur ycombinator j'ai vu quelqu'un dire que bon ça va c'est bon après tout si on appliquait le CoC de node à Linux ça fait très longtemps qu'on aurait dû virer Linus.

    Moi je suis dans la team virer les gens racistes/sexistes/abusifs sur le champs, mais ça donne tout de même de quoi réfléchir.

    - - - Mise à jour - - -



    Dommage ton point de vu on dirait les affreux centristes qui disent nazi += antifa
    C'est l'impression que ça donne parce que j'ai pas vraiment d'avis. Je vois bien que ça pose un problème, y a de plus en plus de cas similaires dans l'opensource/freesoftware mais je vois pas de solution évidente... c'est pas un sujet auquel j'ai beaucoup réfléchi.

  2. #5282
    Citation Envoyé par Orhin Voir le message
    Si oui, y'en a pas vraiment besoin vu qu'elle sont définies au niveau des modules (généralement dans un fichier juste à côté).

    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.

  3. #5283
    Citation Envoyé par Dynames Voir le message
    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

  4. #5284
    Citation Envoyé par Orhin Voir le message
    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.

  5. #5285
    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.

  6. #5286
    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.

    Code:
    path: articles, loadChildren: 'app/article/article.module#ArticleModule' qui est si je ne me trompe pas, le lazyloading dont tu parlais.
    Derrière, j'ai voulu charger SharedModule dans ArticleModule :
    Code:
    imports: [ArticleRoutingModule, SharedModule]
    Comme ça, j'obtiens une erreur 'Maximum call stack' qui semble être lié au fait de faire du chargement de module en boucle.

    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.

  7. #5287
    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.

  8. #5288
    Citation Envoyé par Orhin Voir le message
    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.

  9. #5289
    Citation Envoyé par Dynames Voir le message
    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.
    Perso, tout passe dans des conteneurs maintenant, c'est largement moins chiant.
    "Nobody exists on purpose. Nobody belongs anywhere. We're all going to die. Come watch TV." - Morty Smith

  10. #5290
    Citation Envoyé par Dynames Voir le message
    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.
    Ok, mais les fichiers sur le HEAD de master ne sont pas les bons dans ce cas, y'a que le projet de base généré par Angular CLI et pas tes tests.

  11. #5291
    Citation Envoyé par Orhin Voir le message
    Ok, mais les fichiers sur le HEAD de master ne sont pas les bons dans ce cas, y'a que le projet de base généré par Angular CLI et pas tes tests.
    Hum, je pensais que pour le premier ajout, il aurait tout pris... Autant pour moi. Mise à jour faite.

    Perso, tout passe dans des conteneurs maintenant, c'est largement moins chiant.
    Peux tu développer?

  12. #5292
    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

  13. #5293
    Citation Envoyé par Dynames Voir le message
    Peux tu développer?
    Docker

  14. #5294
    Citation Envoyé par Orhin Voir le message
    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).

  15. #5295
    Oui, les fichiers de route ne sont pas à exporter, seulement à importer dans le module qui leur est propre.

  16. #5296
    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.

  17. #5297
    Sous la main non, mais je regarderais lundi au taf si je peux exporter quelque chose de mon projet actuel.

  18. #5298
    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.

  19. #5299


    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 :
    Code:
    *ngFor="let article of (articles | async)"
    Tu utilises un pipe async alors que articles est de type Article[].
    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.

  20. #5300
    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.

  21. #5301
    Citation Envoyé par Dynames Voir le message
    Ouais, je voyais ça. Mais j'essayais de rester en async.
    Faut pas confondre le principe d'être au maximum en asynchrone et le pipe "async" qui a un usage spécifique.

    Citation Envoyé par Dynames Voir le message
    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.
    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.

    Citation Envoyé par Dynames Voir le message
    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.
    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 :
    Code:
    // Component
    
    articles: Article[];
    
    ngOnInit() {
       this.articles = this.articleService.getArticles();
    }
    
    
    // Template
    
    *ngFor="let article of articles"
    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.articleService.getArticles()
            .subscribe(articles => {
                this.articles = articles;
            }):
    }
    
    
    // Template
    
    *ngFor="let article of articles"
    Code:
    // Component
    
    articles: Observable<Article[]>;
    
    ngOnInit() {
       this.articles = this.articleService.getArticles();
    }
    
    
    // Template
    
    *ngFor="let article of articles | async"
    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.
    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 :
    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"
    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.


    4) Tu veux filtrer les données affichées de façon dynamique (ce qui correspond à ton cas d'usage) :
    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>
    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.
    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 :
    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);
            }
        );
    }
    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é).
    Dernière modification par Orhin ; 31/08/2017 à 17h12. Motif: correction typo

  22. #5302
    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).
    Effectivement, c'est la que j'avais mal compris les méthodes.

    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é)?

  23. #5303
    Ah mon avis l'erreur provient plutôt d'un "this.page" que tu aurais oublié de transformé en "page" dans :
    Code:
    articles.slice((page - 1) * this.itemPerPage, page * this.itemPerPage);
    this.page est un Subject<number>, ce qui est équivalent à un Observable<number>, donc un flux de nombre.
    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".

  24. #5304
    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 un
    Code:
    itemPerPage = Object.keys(articles).lenght
    avant le return dans le OnInit, pour avoir le bon nombre de page.

    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

    Code:
    (articles, page) => {
                return articles.slice((page - 1) * this.itemPerPage, page * this.itemPerPage);
    }
    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.
    Dernière modification par Dynames ; 04/09/2017 à 09h59.

  25. #5305
    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) :
    Code:
    this.page.next(this.initialPage)
    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:
    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);
            }
        );
    }
    L'opérateur "startWith" renvoie un Observable/Subject contenant le flux initial + une valeur ajoutée au début.

  26. #5306
    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.

  27. #5307
    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

  28. #5308
    @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.

    Citation Envoyé par Dynames Voir le message
    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.
    Il y a un problème sur la façon dont tu as intégré cette modification :
    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);
          }
        );
    }
    De la façon dont tu as écris ça, tu fais un combineLatest sur 3 flux différents (au lieu des 2 initiaux).
    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);
          }
        );
    }

  29. #5309
    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.

  30. #5310
    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 :
    Code:
    createArticle(article: Article): void {
      this.articleService.createArticle(article)
        .map(articles => {
          this.articles.push(articles);
          this.selectedArticle = null;
        });
    }
    Absolument rien ne va se passer car tu n'as pas souscris à l'observable renvoyé par la méthode createArticle() de articleService.
    Il faut que tu fasse :
    Code:
    createArticle(article: Article): void {
      this.articleService.createArticle(article)
        .subscribe(articles => {
          this.articles.push(articles);
          this.selectedArticle = null;
        });
    }
    (idem pour deleteArticle)

    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 :
    Code:
    createArticle(article: Article): void {
      this.articleService.createArticle(article)
        .subscribe(articles => {
          this.selectedArticle = null;
        });
    }
    (idem pour deleteArticle)

    Tu as déjà cette partie là qui se charge de récupérer la liste des articles depuis ton service :
    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);
       }
    );
    C'est donc à la méthode getArticles() de articleService de te renvoyer la liste mise à jour après chaque opération de CRUD.
    J'ai fait

    Pour cela on va modifier ton service :
    Spoiler Alert!

    Code:
    @Injectable()
    export class ArticleService {
    
      private headers = new Headers({ 'Content-Type': 'application/json' });
      private articlesUrl = './assets/articles.json';
    
      // buffer qui va stocker la dernière version de la liste des articles
      // les components et les autres services peuvent s'y abonner
      private articles: ReplaySubject<Articles[]> = new ReplaySubject<Articles[]>(1);
    
      constructor(private http: Http) { }
    
      loadArticles(): Observable<Article[]> {
        return this.http.get(this.articlesUrl)
          .map(response => response.json())
          .catch(this.handleError);
      }
    
      getArticles(): Observable<Article[]> {
        return this.articles;
      }
    
      getArticle(id: number): Observable<Article> {
        const url = `${this.articlesUrl}/${id}`;
        return this.http.get(url)
          .map(response => response.json().data as Article)
          .catch(this.handleError);
      }
    
      createArticle(article: Article): Observable<Article> {
        // on récupère la dernière liste des articles dans le buffer et on la met à jour pour propager cette opération
        // le take(1) est là pour éviter une boucle infinie
        this.articles.take(1).subscribe(articles => {
          articles.push(article);
          this.articles.next(articles);
        }):
        return this.http
          .post(this.articlesUrl, JSON.stringify(article), { headers: this.headers })
          .map(res => res.json().data as Article)
          .catch(this.handleError);
      }
    
      updateArticle(article: Article): Observable<Article> {
        this.articles.take(1).subscribe(articles => {
          const index = this.articles.findIndex(a => a.id === article.id);
          if(index !== -1) {
            articles[index] = article;
            this.articles.next(articles);
        }):
        const url = `${this.articlesUrl}/${article.id}`;
        return this.http
          .put(url, JSON.stringify(article), { headers: this.headers })
          .map(() => article)
          .catch(this.handleError);
      }
    
      deleteArticle(article: Article): Observable<void> {
        this.articles.take(1).subscribe(articles => {
          const index = this.articles.findIndex(a => a.id === article.id);
          if(index !== -1) {
            articles.splice(index, 1);
            this.articles.next(articles);
        }):
        const url = `${this.articlesUrl}/${article.id}`;
        return this.http.delete(url, { headers: this.headers })
          .map(() => null)
          .catch(this.handleError);
      }
    
      private handleError(error: any): Promise<any> {
        console.error('An error occurred', error);
        return Promise.reject(error.message || error);
      }
    }


    Ainsi que ton component liste :
    Spoiler Alert!

    Code:
    @Component({
      selector: 'app-liste-article',
      templateUrl: './liste-article.component.html',
      styleUrls: ['./liste-article.component.css']
    })
    export class ListeArticleComponent implements OnInit {
    
      articles: Observable<Article[]>;
      selectedArticle: Article;
      initialPage = 1;
      itemPerPage = 2;
      totalItems = 120;
      page: Subject<number> = new Subject<number>();
    
      constructor(private router: Router, private articleService: ArticleService) { }
    
      ngOnInit() {
        this.articleService.loadArticles();
        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);
          }
        );
      }
    
      onSelect(article: Article) {
        this.selectedArticle = article;
        this.router.navigate(['../articles', this.selectedArticle.id ]);
      }
    
      createArticle(article: Article): void {
        this.articleService.createArticle(article)
          .subscribe(articles => {
            this.selectedArticle = null;
          });
      }
    
      deleteArticle(article: Article): void {
        this.articleService.deleteArticle(article)
          .subscribe(() => {
            if (this.selectedArticle === article) { this.selectedArticle = null; }
          });
      }
    }


    Et ton component détail :
    Spoiler Alert!

    Code:
    @Component({
      selector: 'app-detail-article',
      templateUrl: './detail-article.component.html',
      styleUrls: ['./detail-article.component.css']
    })
    export class DetailArticleComponent implements OnInit {
    
      constructor(private route:  ActivatedRoute, private router: Router, private articleService: ArticleService) { }
    
      article: Article;
    
      ngOnInit() {
        const id =  this.route.snapshot.params['id'];
        this.getArticle(id);
      }
    
      private getArticle(id: string): void {
        if (!id) {
          this.article = new Article();
          return;
        }
    
        this.articleService.getArticle(Number(id))
          .subscribe(article => {
          if (article) {
            this.article = article;
          } else {
            this.gotoList(); // id not found; navigate to list
          }
        });
      }
    
      save(): void {
        this.articleService.updateArticle(this.article).subscribe();
      }
    
      cancel() { this.gotoList(); }
    
      gotoList() {
        this.router.navigate(['../'], {relativeTo: this.route});
      }
    }

Page 177 sur 310 PremièrePremière ... 77127167169170171172173174175176177178179180181182183184185187227277 ... DernièreDernière

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •