Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Angular] Can't bind to 'formGroup'

28 juillet 2020 à 15:19:57

Hello à tous,

je n'arrive pas à avancer beaucoup sur la partie 2 du dernier bloc du Cours intitulé "developpez des applications web avec angular".

Il s'agit de la partie intitulée "écoutez l'utilisateur avec les forms - méthode réactive"

J'ai une erreur dans le terminal, NG8002: Can't bind to 'formGroup' since it isn't a known property of 'form'. Error occurs in the template of component NewUserComponent.

s'il vous plait, pouvez-vous m'aider ?

Bonne journée

Voici un morceau de code, le app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { MonPremierComponent } from './mon-premier/mon-premier.component';
import { PostComponent } from './post/post.component';
import { PostService } from './services/post.service';
import { AuthComponent } from './auth/auth.component';
import { PostViewComponent } from './post-view/post-view.component';
import {RouterModule, Routes} from '@angular/router';
import {AuthService} from './services/auth.service';
import { SinglePostComponent } from './single-post/single-post.component';
import { FourOhFourComponent } from './four-oh-four/four-oh-four.component';
import {AuthGuard} from './services/auth-guard.service';
import { EditPostComponent } from './edit-post/edit-post.component';
import { UserListComponent } from './user-list/user-list.component';
import {UserService} from './services/user.service';
import {NewUserComponent} from './new-user/new-user.component';


const appRoutes: Routes = [
  { path: 'posts', canActivate: [AuthGuard], component: PostViewComponent },
  { path: 'posts/:id', canActivate: [AuthGuard], component: SinglePostComponent},
  { path: 'edit', canActivate: [AuthGuard], component: EditPostComponent },
  { path: 'auth', component: AuthComponent },
  { path: 'users', component: UserListComponent },
  { path: 'new-user', component: NewUserComponent },
  { path: '', component: PostViewComponent },
  { path: 'not-found', component: FourOhFourComponent },
  { path: '**', redirectTo: 'not-found' }
];

@NgModule({
  declarations: [
    AppComponent,
    MonPremierComponent,
    PostComponent,
    AuthComponent,
    PostViewComponent,
    SinglePostComponent,
    FourOhFourComponent,
    EditPostComponent,
    UserListComponent,

  ],
  imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule,
    RouterModule.forRoot(appRoutes),


  ],
  providers: [
    PostService,
    AuthService,
    AuthGuard,
    UserService
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Ainsi que le template :

<div class="col-sm-8 col-sm-offset-2">
  <form [formGroup]="userForm" (ngSubmit)="onSubmitForm()">
    <div class="form-group">
      <label for="firstName">Prénom</label>
      <input type="text" class="form-control" id="firstName" formControlName="firstName">
    </div>
    <div class="form-group">
      <label for="lastName">Nom</label>
      <input type="text" class="form-control" id="lastName" formControlName="lastName">
    </div>
    <div class="form-group">
      <label for="email">Adresse mail</label>
      <input type="text" class="form-control" id="email" formControlName="email">
    </div>
    <div class="form-group">
      <label for="drinkPreference">Quelle boisson préférez-vous ?</label>
      <select id="drinkPreference" class="form-control" formControlName="drinkPreference">
        <option value="Coca">Coca</option>
        <option value="Pepsi">Pepsi</option>
      </select>
    </div>
    <button class="btn btn-primary" type="submit" [disabled]="userForm.invalid">Soumettre</button>
  </form>
</div>

PS : Avez-vous besoin de voir un autre fichier ?

-
Edité par Benzouye 30 juillet 2020 à 10:31:45

  • Partager sur Facebook
  • Partager sur Twitter
28 juillet 2020 à 15:47:39

Salut. Tu ne devrais pas ajouter "NewUserComponent" dans les déclarations des composants?
  • Partager sur Facebook
  • Partager sur Twitter
28 juillet 2020 à 16:01:05

Salut,

qu'entends-tu par là ?

J'ai la ligne 20 dans le app.module :

import {NewUserComponent} from './new-user/new-user.component';
  • Partager sur Facebook
  • Partager sur Twitter
28 juillet 2020 à 16:56:13

declarations: [
    AppComponent,
    MonPremierComponent,
    PostComponent,
    AuthComponent,
    PostViewComponent,
    SinglePostComponent,
    FourOhFourComponent,
    EditPostComponent,
    UserListComponent,
    NewUserComponent
  ],
  • Partager sur Facebook
  • Partager sur Twitter
28 juillet 2020 à 19:48:43

Merci beaucoup kulturman, ça fonctionne ! Je peux à présent créer un utilisateur.

Toutefois j'ai quelques Warnings à présent, voici un exemple :

\src\app\app.component.ts depends on 'rxjs/Observable'. CommonJS or AMD dependencies can cause optimization bailouts.

Il y en a plusieurs dans le Terminal : pour app.component.ts, post.service.ts, Subject.js, Rx.js, Observable.js. Savez-vous d'où cela provient ?

-
Edité par ElieL. 28 juillet 2020 à 19:52:44

  • Partager sur Facebook
  • Partager sur Twitter
29 juillet 2020 à 12:22:23

Désolé je ne sais pas comment résoudre ça, mais je pense que ce n'est pas grave pour le moment, tu peux continuer sans problème dans ton apprentissage
  • Partager sur Facebook
  • Partager sur Twitter
29 juillet 2020 à 23:45:52

Merci encore, j'ai pu avancer, jusqu'à bloquer sur une autre erreur :

ERROR in HostResourceResolver: could not resolve ./book-list.component.css in context of J:/00_Prod/Current/Angular_courses/Angular_OpenClassroom/TP/bookshelves/src/app/book-list/book-list.component.ts)



La seule chose que je pense avoir de différent avec le code de la leçon est : le nom d'un component. J'ai écrit single-form au lieu de book-form.
Un autre aveu, j'ai choisi avec les flèches directionnelles scss au lieu de taper --css au moment de la création du projet.

Je remarque que dans mon app.module, la ligne suivante est soulignée en rouge :

import { SingleFormComponent } from './book-list/single-form/single-form.component';


Il est écrit comme indication :

TS2305: Module '"./book-list/single-form/single-form.component"' has no exported member 'SingleFormComponent'.


Auriez-vous une idée de ce qui peut empêcher le build process ? Merci pour votre aide.

Edit : L'erreur a disparu après avoir changé le nom de fichier dans :

@Component({
  selector: 'app-single-form',
  templateUrl: './single-form.component.html',
  styleUrls: ['./single-form.component.scss']

Et après avoir changé le nom SingleFormComponent :

export class SingleFormComponent implements OnInit {

Cependant, j'ai à présent une autre erreur :

Error: J:\00_Prod\Current\Angular_courses\Angular_OpenClassroom\TP\bookshelves\src\app\models\book.model.ts is missing from the TypeScript compilation. Please make sure it is in your tsconfig via the 'files' or 'include' property.

S'avez-vous d'où elle provient ?

Je précise qu'il y a un Warning au dessus de l'erreur, que je ne comprends pas non plus :

WARNING in ./src/app/models/Book.model.ts
There are multiple modules with names that only differ in casing.
This can lead to unexpected behavior when compiling on a filesystem with other case-semantic.
Use equal casing. Compare these module identifiers:
* J:\00_Prod\Current\Angular_courses\Angular_OpenClassroom\TP\bookshelves\node_modules\@ngtools\webpack\src\index.js!J:\00_Prod\Current\Angular_courses\Angular_OpenClassroom\TP\bookshelves\src\app\models\Book.model.ts
    Used by 2 module(s), i. e.
    J:\00_Prod\Current\Angular_courses\Angular_OpenClassroom\TP\bookshelves\node_modules\@ngtools\webpack\src\index.js!J:\00_Prod\Current\Angular_courses\Angular_OpenClassroom\TP\bookshelves\src\app\book-list\single-book\single-book.component.ts
* J:\00_Prod\Current\Angular_courses\Angular_OpenClassroom\TP\bookshelves\node_modules\@ngtools\webpack\src\index.js!J:\00_Prod\Current\Angular_courses\Angular_OpenClassroom\TP\bookshelves\src\app\models\book.model.ts
    Used by 2 module(s), i. e.
    J:\00_Prod\Current\Angular_courses\Angular_OpenClassroom\TP\bookshelves\node_modules\@ngtools\webpack\src\index.js!J:\00_Prod\Current\Angular_courses\Angular_OpenClassroom\TP\bookshelves\src\app\book-list\single-form\single-form.component.ts

C'est comme si ce fichier Book.model que j'ai créé ainsi que le dossier models n'étaient pas reconnus.





-
Edité par ElieL. 30 juillet 2020 à 10:23:49

  • Partager sur Facebook
  • Partager sur Twitter
30 juillet 2020 à 10:21:27

Essaie de relancer le serveur de développement pour voir. Sinon tu es sûr que le model existe?
  • Partager sur Facebook
  • Partager sur Twitter
30 juillet 2020 à 10:26:49 - Message modéré pour le motif suivant : La demande de l'équipe de modération a été honorée.


Pas d'aide concernant le code par MP, le forum est là pour ça :)

30 juillet 2020 à 10:27:55

Bonjour,

Déplacement vers un forum plus approprié

Le sujet est déplacé de la section Discussions développement vers la section Javascript

  • Partager sur Facebook
  • Partager sur Twitter
Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
30 juillet 2020 à 10:45:18

kulturman, merci pour ta réponse, non, rien n'y fait.
J'ai essayé de supprimer le modèle, et de le recréer, j'ai aussi essayé de renommer le nom du dossier contenant le projet en utilisant des minuscules, au cas où. L'erreur persiste.

Peut-être faut-il éditer le tsconfig ?

-
Edité par ElieL. 30 juillet 2020 à 10:46:37

  • Partager sur Facebook
  • Partager sur Twitter
30 juillet 2020 à 11:04:16

Je n'ai jamais eu à éditer ce fichier. Tu peux montrer l’arborescence de ton projet?
  • Partager sur Facebook
  • Partager sur Twitter
30 juillet 2020 à 11:14:58

Oui, voici une capture d'écran, merci pour ton aide, j'ai renommé le fichier models en Models

arborescence

  • Partager sur Facebook
  • Partager sur Twitter
30 juillet 2020 à 11:31:30

Le dossier "models" tu veux dire? Finalement c'est "models" ou "Models"? Maintenant montre moi où tu utilises le model en question (book.model)
  • Partager sur Facebook
  • Partager sur Twitter
30 juillet 2020 à 11:39:59

Oui le dossier "models" est à présent "Models",

d'après ma connaissance, je l'utilise à trois endroits : book-list.component.ts, single-form.component.ts, et single-book.component.ts

voici les codes :

book-list.component.ts :

import { Component, OnDestroy, OnInit } from '@angular/core';
import { BooksService } from '../services/books.service';
import { Book } from '../Models/book.model';
import { Subscription } from 'rxjs/Subscription';
import { Router } from '@angular/router';

@Component({
  selector: 'app-book-list',
  templateUrl: './book-list.component.html',
  styleUrls: ['./book-list.component.scss']
})
export class BookListComponent implements OnInit, OnDestroy {

  books: Book[];
  booksSubscription: Subscription;

  constructor(private booksService: BooksService, private router: Router) {}

  ngOnInit() {
    this.booksSubscription = this.booksService.booksSubject.subscribe(
      (books: Book[]) => {
        this.books = books;
      }
    );
    this.booksService.emitBooks();
  }

  onNewBook() {
    this.router.navigate(['/books', 'new']);
  }

  onDeleteBook(book: Book) {
    this.booksService.removeBook(book);
  }

  onViewBook(id: number) {
    this.router.navigate(['/books', 'view', id]);
  }

  ngOnDestroy() {
    this.booksSubscription.unsubscribe();
  }
}

single-form.component.ts :

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Book } from '../../Models/book.model';
import { BooksService } from '../../services/books.service';
import { Router } from '@angular/router';

@Component({
  selector: 'app-single-form',
  templateUrl: './single-form.component.html',
  styleUrls: ['./single-form.component.scss']
})
export class SingleFormComponent implements OnInit {

  bookForm: FormGroup;

  constructor(private formBuilder: FormBuilder, private booksService: BooksService,
              private router: Router) { }

  ngOnInit() {
    this.initForm();
  }

  initForm() {
    this.bookForm = this.formBuilder.group({
      title: ['', Validators.required],
      author: ['', Validators.required],
      synopsis: ''
    });
  }

  onSaveBook() {
    const title = this.bookForm.get('title').value;
    const author = this.bookForm.get('author').value;
    const synopsis = this.bookForm.get('synopsis').value;
    const newBook = new Book(title, author);
    newBook.synopsis = synopsis;
    this.booksService.createNewBook(newBook);
    this.router.navigate(['/books']);
  }
}


et single-book.component.ts :

import { Component, OnInit } from '@angular/core';
import {Book} from '../../Models/Book.model';
import {ActivatedRoute, Router} from '@angular/router';
import {BooksService} from '../../services/books.service';

@Component({
  selector: 'app-single-book',
  templateUrl: './single-book.component.html',
  styleUrls: ['./single-book.component.scss']
})
export class SingleBookComponent implements OnInit {

  book: Book;

  constructor(private route: ActivatedRoute,
              private booksService: BooksService,
              private router: Router) { }

  ngOnInit() {
    this.book = new Book('', '');
    const id = this.route.snapshot.params['id'];
    this.booksService.getSingleBook(+id).then(
      (book: Book) => {
        this.book = book;
      }
    );
  }

  onBack() {
    this.router.navigate(['/books']);
  }
}


Merci encore !

Edit:

et puis aussi dans book.service.ts :

import { Injectable } from '@angular/core';
import {Book} from '../Models/Book.model';
import {Subject} from 'rxjs';
import * as firebase from 'firebase';
import DataSnapshot = firebase.database.DataSnapshot;

@Injectable()
export class BooksService {

  books: Book[] = [];
  booksSubject = new Subject<Book[]>();

  constructor() {
    this.getBooks();
  }

  // tslint:disable-next-line:typedef
  emitBooks() {
    this.booksSubject.next(this.books);
  }

  // tslint:disable-next-line:typedef
  saveBooks() {
    firebase.database().ref('/books').set(this.books);
  }

  // tslint:disable-next-line:typedef
  getBooks() {
    firebase.database().ref('/books')
      .on('value', (data: DataSnapshot) => {
          this.books = data.val() ? data.val() : [];
          this.emitBooks();
        }
      );
  }

  getSingleBook(id: number) {
    return new Promise(
      (resolve, reject) => {
        firebase.database().ref('/books/' + id).once('value').then(
          (data: DataSnapshot) => {
            resolve(data.val());
          }, (error) => {
            reject(error);
          }
        );
      }
    );
  }

  createNewBook(newBook: Book) {
    this.books.push(newBook);
    this.saveBooks();
    this.emitBooks();
  }

  removeBook(book: Book) {
    const bookIndexToRemove = this.books.findIndex(
      (bookE1) => {
        if(bookE1 === book) {
          return true;
        }
      }
    );
    this.books.splice(bookIndexToRemove, 1);
    this.saveBooks();
    this.emitBooks();
  }
}


Autant pour moi !

dans la ligne d'import le "b" de book.model doit être minuscule dans book.service.ts et single-book.component.ts :

à présent, çà compile ! Quel plaisir :D

Edit edit :

Pour une raison que j'ignore le template de single-book.component fonctionne mal, il n'affiche pas les détails. Pourtant j'ai bien les book.title et book.author :

<div class="row">
  <div class="col-xs-12">
    <h1>{{ book.title }}</h1>
    <h3>{{ book.author }}</h3>
    <button class="btn btn-default" (click)="onBack()">Retour</button>
  </div>
</div>


Avez-vous une idée de ce qui peut être cassé ? Lorsque je tape {{ book }} pour tester dans chrome, il s'affiche [Object] [Object]

-
Edité par ElieL. 30 juillet 2020 à 23:57:55

  • Partager sur Facebook
  • Partager sur Twitter
1 août 2020 à 10:43:50

Je pense que c'est un problème de serveur car lorsque je rafraichit la page de mes livres, ils disparaissent.

Doit-on le démarrer, ou bien quelque chose de la sorte ?

J'ai dans le app.component.ts ceci dans le constructor :

const firebaseConfig = {
      apiKey: 'AIzaSyAHnevYHYk2sumn0QFlF3HAo_2GgID8OFY',
      authDomain: 'bookshelves-f1336.firebaseapp.com',
      databaseURL: 'https://bookshelves-f1336.firebaseio.com',
      projectId: 'bookshelves-f1336',
      storageBucket: 'bookshelves-f1336.appspot.com',
      messagingSenderId: '1043789159276',
      appId: '1:1043789159276:web:92d7408c58c44451c13149',
      measurementId: 'G-4VW3GW2JX8'
    };
    // Initialize Firebase
    firebase.initializeApp(firebaseConfig);
    firebase.analytics();

  }

Cependant dans les parametres de firebase, ils me proposent soit CDN :

<!-- The core Firebase JS SDK is always required and must be listed first -->
<script src="https://www.gstatic.com/firebasejs/7.17.1/firebase-app.js"></script>

<!-- TODO: Add SDKs for Firebase products that you want to use
     https://firebase.google.com/docs/web/setup#available-libraries -->
<script src="https://www.gstatic.com/firebasejs/7.17.1/firebase-analytics.js"></script>

<script>
  // Your web app's Firebase configuration
  var firebaseConfig = {
    apiKey: "AIzaSyAHnevYHYk2sumn0QFlF3HAo_2GgID8OFY",
    authDomain: "bookshelves-f1336.firebaseapp.com",
    databaseURL: "https://bookshelves-f1336.firebaseio.com",
    projectId: "bookshelves-f1336",
    storageBucket: "bookshelves-f1336.appspot.com",
    messagingSenderId: "1043789159276",
    appId: "1:1043789159276:web:92d7408c58c44451c13149",
    measurementId: "G-4VW3GW2JX8"
  };
  // Initialize Firebase
  firebase.initializeApp(firebaseConfig);
  firebase.analytics();
</script>

Soit Configuration :

const firebaseConfig = {
  apiKey: "AIzaSyAHnevYHYk2sumn0QFlF3HAo_2GgID8OFY",
  authDomain: "bookshelves-f1336.firebaseapp.com",
  databaseURL: "https://bookshelves-f1336.firebaseio.com",
  projectId: "bookshelves-f1336",
  storageBucket: "bookshelves-f1336.appspot.com",
  messagingSenderId: "1043789159276",
  appId: "1:1043789159276:web:92d7408c58c44451c13149",
  measurementId: "G-4VW3GW2JX8"
};

Mais je ne sais pas où coller ces lignes, ni quoi faire de leur code ! Ils disent de copier/coller ces scripts en bas de ma balise <body> mais je n'en vois pas dans mes templates.

Edit : Okay les amis. Les éléments s'affichent. Mon problème pour ceux qui rencontreraient le mêmes difficultés que moi :

Il s'agissait de parametrer dans la console de firebase : en real time database et non en cloud, puis j'ai modifié les règles en 'true' pour lecture et 'true' pour écriture.


-
Edité par ElieL. 1 août 2020 à 15:15:33

  • Partager sur Facebook
  • Partager sur Twitter
5 avril 2022 à 15:43:54

Bonjour,

J'ai la même erreur en suivant le même cours : Can't bind to 'formGroup' since it isn't a known property of 'form'

Ma version d'Angular : 13.3.0

Edit : j'ai trouvé la solution - il ne faut pas oublier d'importer "ReactiveFormsModule" dans app.module.ts, ainsi on a :

imports: [
    BrowserModule,
    AppRoutingModule,
    ReactiveFormsModule
  ]

-
Edité par Nonozor_44 5 avril 2022 à 15:52:14

  • Partager sur Facebook
  • Partager sur Twitter
13 février 2024 à 18:58:23 - Message modéré pour le motif suivant : Merci d’utiliser le bouton code pour insérer un code sur le forum


13 février 2024 à 19:23:40

@aminatadiome Bonsoir, merci de ne pas déterrer d'ancien sujet pour une nouvelle question, créer votre propre sujet en respectant les règles du forum à savoir que le code informatique doit être insérer sur le forum à l'aide du bouton code </> de la barre d'outil du forum.

Merci de lire les règles du forum AVANT de créer un sujet.

Déterrage

Citation des règles générales du forum :

Avant de poster un message, vérifiez la date du sujet dans lequel vous comptiez intervenir.

Si le dernier message sur le sujet date de plus de deux mois, mieux vaut ne pas répondre.
En effet, le déterrage d'un sujet nuit au bon fonctionnement du forum, et l'informatique pouvant grandement changer en quelques mois il n'est donc que rarement pertinent de déterrer un vieux sujet.

Au lieu de déterrer un sujet il est préférable :

  • soit de contacter directement le membre voulu par messagerie privée en cliquant sur son pseudonyme pour accéder à sa page profil, puis sur le lien "Ecrire un message"
  • soit de créer un nouveau sujet décrivant votre propre contexte
  • ne pas répondre à un déterrage et le signaler à la modération

Liens conseillés

Je ferme ici.

-
Edité par AbcAbc6 13 février 2024 à 19:26:16

  • Partager sur Facebook
  • Partager sur Twitter