1
votes

Le bootstrap CSS ne fonctionne pas dans le sous-composant Angular

Je rencontre un problème lors de l'inclusion de mon composant enfant dans mon composant parent dans Angular 8. Mon composant enfant ne contient qu'une liste déroulante. Maintenant, lorsque j'inclus le même dans le composant parent et le CSS utilisé dans le div du composant parent, la sortie d'affichage arrive comme prévu.

Composant parent:

<div class="col-sm-5">
  <select [(ngModel)]='countryDetails.default' class="form-control form-control-lg">
    <option *ngFor="let province of countryDetails.details" value={{country.id}}>
      {{country.value}}
    </option>
  </select>
</div>

Composant enfant

 <div class="col-lg-12">
      <div class="form-group row">
        <label class="col-sm-1 col-form-label-lg font-weight-bold">Country</label>
        <app-country></app-country>
      </div>
    </div>

Mais maintenant pour réduire le codage prévu pour déplacer le div class = "col-sm- 5 "dans le composant enfant.

Nouveau codage qui ne fonctionne pas:

Composant parent:

<select [(ngModel)]='countryDetails.default' class="form-control form-control-lg">
  <option *ngFor="let province of countryDetails.details" value={{country.id}}>
    {{country.value}}
  </option>
</select>

Composant enfant:

<div class="col-lg-12">
  <div class="form-group row">
    <label class="col-sm-1 col-form-label-lg font-weight-bold">Country</label>
    <div class="col-sm-5">
      <app-country >
      </app-country>
    </div>
  </div>
</div>

Dans la deuxième partie, si j'étends le code HTML de sortie via la console Web, alors j'ai constaté que le CSS est inclus dans le code mais alors le comportement est différent.

Notez également que j'utilise du CSS bootstrap.

Toute aide serait appréciable.


4 commentaires

Utilisez-vous uniquement le CSS Bootstrap ou avez-vous également inclus le JS de Bootstrap?


Dans la boucle option , est-ce country.id ou province.id (et province.value )?


Prenez-le comme identifiant de pays ou détails du pays. Ce ne sont que des données de démonstration fournies à titre de référence. Notez également que le JS de Bootstrap n'est pas inclus.


@Souvik Utilisez le sélecteur d'attribut pour votre composant enfant, voir ma réponse


6 Réponses :


0
votes

Si vous utilisez une version antérieure d'Angular, le paramètre par défaut d'encapsulation était différent. Vous pouvez essayer

@Component({
    // ...
    encapsulation: ViewEncapsulation.None
})

pour le composant enfant de votre fichier .ts.


0 commentaires

2
votes

c'est parce que le dernier HTML généré maintenant est comme ceci,

    <div class="col-lg-12">
      <div class="form-group row">
        <label class="col-sm-1 col-form-label-lg font-weight-bold">Country</label>
           <div class="col-sm-5">
              <app-country>
                  <select [(ngModel)]='countryDetails.default' class="form-control form-control-lg">
                     <option *ngFor="let province of countryDetails.details" value= 
                       {{country.id}}>
                       {{country.value}}
                     </option>
                   </select>
              </app-country>
           </div>
      </div>
 </div>

Mais plus tôt,

<div class="col-lg-12">
      <div class="form-group row">
        <label class="col-sm-1 col-form-label-lg font-weight-bold">Country</label>
         <app-country>
           <div class="col-sm-5">
                <select [(ngModel)]='countryDetails.default' class="form-control form-control-lg">
                  <option *ngFor="let province of countryDetails.details" value= 
                  {{country.id}}>
                  {{country.value}}
                  </option>
                </select>
             </div>
        </app-country>
      </div>
 </div>

Comme vous pouvez le voir position est différente dans vos approches. Avant col-sm-5 et après col-sm-5

Cela provoque la classe Bootstrap row pour casser le css :)


0 commentaires

1
votes

Mise à jour: Solution 2

Référence de https://stackoverflow.com/a/ 52717242/5061139

Vous pouvez créer une directive puis supprimer dynamiquement l'élément parent.

<div class="col-lg-12">
  <div class="form-group row">
    <label class="col-sm-1 col-form-label-lg font-weight-bold">Country</label>
    <div class="col-sm-5" app-country>
    </div>
  </div>
</div>

Et pour l'utiliser comme ceci,

@Component({
  selector: '[app-country]',
  template:  './app-country.component.html',
  styleUrls: ['./app-country.component.css']
})

Et un composant enfant comme celui-ci:

<div class="col-lg-12">
  <div class="form-group row">
    <label class="col-sm-1 col-form-label-lg font-weight-bold">Country</label>
     <app-country>
       <div class="col-sm-5">
            <select [(ngModel)]='countryDetails.default' class="form-control form-control-lg">
              <option *ngFor="let province of countryDetails.details" value= 
              {{country.id}}>
              {{country.value}}
              </option>
            </select>
         </div>
    </app-country>
  </div>

Cela répondra à vos exigences. p>

----->

Donc, le problème avec votre approche est qu'il y a un wrapper d'élément supplémentaire de votre composant enfant lorsqu'il est rendu dans le DOM . Ainsi, le HTML rendu est comme

<div class="col-sm-5" remove-wrapper>
  <select [(ngModel)]='countryDetails.default' class="form-control form-control-lg">
    <option *ngFor="let province of countryDetails.details" value= . {{country.id}}>
      {{country.value}}
    </option>
  </select>
</div>

Comme vous pouvez le voir, il y a plus de wrapper dans le HTML. Pour résoudre ce problème, vous pouvez utiliser le sélecteur d'attributs pour votre composant enfant.

<div class="col-lg-12">
  <div class="form-group row">
    <label class="col-sm-1 col-form-label-lg font-weight-bold">Country</label>
    <app-country></app-country>
  </div>
</div>

Et dans votre composant parent, utilisez ceci comme:

XXX

Maintenant, vous n'obtiendrez pas de wrapper d'élément supplémentaire et votre bootstrap css fonctionnera très bien. J'espère que cela aidera à résoudre votre problème.


3 commentaires

Ce que j'essaye, c'est de déplacer le div total dans mon composant enfant. Parce que partout où ce composant sera importé sera avec la même taille de colonne et les mêmes détails. Mon intention est de réduire le code lors de l'importation.


@Souvik J'ai mis à jour la réponse et proposé une autre solution pour votre cas


Hé, cela a résolu mon problème initial du CSS déroulant, mais comme l'étiquette sera la même, comment puis-je déplacer l'étiquette dans le composant. Avec ce code, cela supprime l'étiquette si je la mets dans le composant.



0
votes

La réponse de @ ankit-agarwal est pertinente. Pourtant, si vous voulez forcer la classe col-sm-5 sur votre composant, à l'intérieur, vous devez utiliser HostBinding . HostBinding vous permet d'attacher des attributs / classes / styles à l'élément Dom hébergeant le composant ou la directive.

Donc, dans votre exemple, et en conservant le sélecteur app-country (Je n'aime pas vraiment les sélecteurs d'attributs pour les composants) dont vous auriez besoin:

@Component({
  selector: 'app-country',
  ...
})
export class CountryComponent {
  @HostBinding('class.col-sm-5') cssWidthClass = true;
}
<!-- country.component.html -->
<!-- you don't need the div, because we are going to attach the class
     to the app-country tag itself. -->
<select [(ngModel)]='countryDetails.default' class="form-control form-control-lg">
  <option *ngFor="let province of countryDetails.details" value={{country.id}}>
    {{country.value}}
  </option>
</select>
/* country.component.css */
/* This is necessary in order to have the app-country element behave as a
 * div in the page layout. */
:host {
  display: block;
}

Le true demandera à Angular de sortir la classe col-sm-5 dans la liste des classes présentes dans la balise d'hébergement ( app-country ).
Vous pouvez avoir une propriété Input supplémentaire utilisée pour définir le champ cssWidthClass (le nom n'est vraiment pas important, d'ailleurs) sur null , afin de pas affiche la classe col-sm-5 , si le besoin s'en fait sentir.


1 commentaires

Cette solution fonctionne également pour moi. Mais pouvez-vous me dire comment puis-je ajouter l'étiquette également sous le composant.



4
votes

@Souvik, Vous devez d'abord installer votre bootstrap et la nécessité de donner le lien des fichiers bootstrap dans "angular.json".

Voici les façons d'utiliser le bootstrap dans un projet angulaire, j'espère que cela fonctionnera pour vous.

Méthode 1: Utilisation de la CLI angulaire (installation npm).

Pour En installant un Bootstrap dans votre projet, vous pouvez utiliser la commande suivante

@import url("bootstrap.min.css"); 

Après cela, vous devez l'ajouter dans votre fichier "angular.json", qui se trouve à la racine du projet

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

Après l'ajout, vous devez fermer et exécuter votre projet une fois pour qu'il fonctionne correctement

Méthode 2: Utilisation d'un CDN (Copier et méthode Coller). Vous pouvez utiliser une ancienne façon d'utiliser le bootstrap dans le projet, l'URL du chemin est ajoutée à l'index.html pour référencé global.

"styles": [

              "node_modules/bootstrap/dist/css/bootstrap.min.css",
              "src/styles.scss"
          ],

Méthode 3: Ajout de fichiers CSS bootstrap à votre projet (à l'aide de l'importation CSS): Vous pouvez directement ajouter des dossiers d'amorçage à votre répertoire d'actifs dans votre projet angulaire et référencer le dossier directement dans votre style.css ou style.scss en utilisant

npm install bootstrap --save


0 commentaires

0
votes

Votre composant enfant sera rendu à l'intérieur de la balise du composant parent (comme ci-dessous).

eg. <div class="col-sm-5" app-country></div>

Modifiez donc votre css en conséquence ou utilisez le composant en utilisant le sélecteur d'attribut dans le parent

XXX


0 commentaires