Como resolver o problema do View Encapsulation no Angular8?

8

Eu tenho componente pai e componente filho. Componente filho criado como um componente modal. Então, eu incluí o seletor de componente filho no componente pai e defini que o encapsulamento de exibição é nenhum, de modo que ele leve o componente pai css e tudo e está funcionando também, mas o componente pai tem o id do papel que aplica #paper id aplicando css libary de terceiros (rappidjs) (por Diagramação SVG). O mesmo componente filho tem o ID #dataMapper. mas aqui o css de terceiros não está recebendo porque o componente filho está definido como 'encapsulation: ViewEncapsulation.None'. Se eu vou removê- encapsulation: ViewEncapsulation.Nonelo está funcionando, mas modal não está funcionando. todos os modais carregando em vez de onclick. Como resolver este problema, por favor, aconselhe-me alguém.

Codificação:

TS do componente pai

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

export class DataModelComponent implements OnInit{

// Modal

openModal(id: string) {
  this.modalApp = true;
  this.modalService.open(id);
}

closeModal(id: string) {
  this.modalService.close(id);
}

HTML do componente pai

<div id="toolbar">
    <div class="tool-bar-section">
    <button class="btn" (click)="openModal('custom-modal-1');"><i class="fa fa-file-excel-o" style="font-size: 24px"></i></button>     
    </div>   
</div>
<div id="paper"> </div> ( this dom taking thirdparty css)

<app-modal id="custom-modal-1">           
    <h1 class="head-bar">Data Model - Import Excel  <a href="#" class="close-icon" (click)="closeModal('custom-modal-1');"><i class="fa fa-times-circle-o" aria-hidden="true"></i></a></h1>
    <div class="modal-content-section">
     <ul>
         <li><a href="#" (click)="closeModal('custom-modal-1');openModal('custom-modal-2');">Create New Schema</a></li>
         <li><a href="#" (click)="closeModal('custom-modal-1');openModal('custom-modal-3');">Import Data to existing schema</a></li>
     </ul>       
    </div>        
</app-modal>
<app-modal id="custom-modal-2">       
    <h1 class="head-bar">Data Model - Import Excel  <a href="#" class="close-icon" (click)="closeModal('custom-modal-2');"><i class="fa fa-times-circle-o" aria-hidden="true"></i></a></h1>
    <div class="modal-content-section">
        <div id="dataMapper"></div>       ( this dom is not taking thirdparty css)
        <p><a href="#" (click)="closeModal('custom-modal-2');openModal('custom-modal-4');">Data Mapping</a></p>
    </div>
</app-modal>

HTML do componente filho

<div class="app-modal">
    <div class="app-modal-body">
        <ng-content></ng-content>
    </div>
</div>
<div class="app-modal-background"></div>

Ts de componente filho

@Component({
  selector: 'app-modal',
  templateUrl: './modal.component.html',
  styleUrls: ['./modal.component.css'],
  encapsulation: ViewEncapsulation.None
})
export class ModalComponent implements OnInit, OnDestroy {

  @Input() id: string;
  private element: any;

  constructor(private modalService: ModalService, private el: ElementRef) {
      this.element = el.nativeElement;
  }

  ngOnInit(): void {
      // ensure id attribute exists
      if (!this.id) {
          console.error('modal must have an id');
          return;
      }

      // move element to bottom of page (just before </body>) so it can be displayed above everything else
      document.body.appendChild(this.element);

      // close modal on background click
      this.element.addEventListener('click', el => {
          if (el.target.className === 'app-modal') {
              this.close();
          }
      });

      // add self (this modal instance) to the modal service so it's accessible from controllers
      this.modalService.add(this);
  }

  // remove self from modal service when component is destroyed
  ngOnDestroy(): void {
      this.modalService.remove(this.id);
      this.element.remove();
  }

  // open modal
  open(): void {
      this.element.style.display = 'block';
      document.body.classList.add('app-modal-open');
  }

  // close modal
  close(): void {
      this.element.style.display = 'none';
      document.body.classList.remove('app-modal-open');
  }

}

Código de serviço modal

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class ModalService {

  private modals: any[] = [];

  add(modal: any) {
      // add modal to array of active modals
      this.modals.push(modal);
  }

  remove(id: string) {
      // remove modal from array of active modals
      this.modals = this.modals.filter(x => x.id !== id);
  }

  open(id: string) {
      // open modal specified by id
      const modal = this.modals.find(x => x.id === id);
      modal.open();
  }

  close(id: string) {
      // close modal specified by id
      const modal = this.modals.find(x => x.id === id);
      modal.close();
  }
}

Entre em contato se precisar de mais detalhes.

bagya
fonte
3
Tente adicionar um exemplo de stackblitz em vez de publicar um monte de código.
Akhil Aravind 03/03
@AkhilAravind - Adicionar stackblitiz pode levar mais tempo. porque é grande aplicativo e eu coloquei o código apenas onde o problema.
bagya 03/03
Não precisamos de todo o bloco de códigos, apenas uma amostra mínima para reproduzir o problema.
Akhil Aravind 03/03
2
você pode postar alguns exemplos do css que deve ser aplicado e dos seletores? não está claro o que está acontecendo de errado aqui. Se esse css de terceiros for baseado em IDs, isso será muito problemático se esses IDs aparecerem várias vezes na página, como se esses componentes fossem reutilizados em qualquer lugar. somente a primeira instância de um id terá os estilos
bryan60
1
Seria útil para todos nós resolver o seu problema se você puder criar um problema reproduzível mínimo no stackblitz. Não inclua todo o seu projeto, apenas a parte em que você está enfrentando esse problema.
PrinceIsNinja 7/03

Respostas:

1

Por causa do seu modal. O modal é criado na parte superior do seu aplicativo (tag fora do corpo, se você procurar o invólucro modal ao inspecioná-lo.)

É a Modal porque a estrutura dom não está sincronizada com a estrutura do componente ng

Então, por que o modal funciona com ng Encapsulation? Porque o seu serviço modal pode lidar com isso.

Mas o arquivo CSS de terceiros não faz parte da sua configuração de compilação angular (ou seja, apenas sass, scss funciona). Portanto, ele ignora qualquer .cssimportação mesmo.

Para resolvê-lo, você pode aplicar o .css globalmente. Ou, se você tem medo de substituir outros estilos globais, renomeie o arquivo css para '_somefile.scss' (preste atenção ao traço '_', é importante).

Em seguida, no arquivo global style.scss do projeto> crie um seletor que corresponda ao seu wrapper modal> abaixo do seletor: adicione uma linha que importe algum arquivo (não adicione extensão)

style.scss

.modal-wrapper {
    @import somepath/somefile
}
Vincent-cm
fonte
0

Conforme descrito por você no problema, você deseja herdar o css do componente pai dentro do componente filho. Então, suponho que você esteja tendo os mesmos elementos HTML nos componentes pai e filhos e não queira duplicar seu css.

Como não conseguimos replicar seu problema e você não criou nenhuma instância do stackblitz. Eu sugeriria uma alternativa melhor que funcione. Encontre-o abaixo:

Podemos especificar vários URLs CSS dentro da styleUrlspropriedade do @Componentobjeto de metadados do decorador. Então, eu sugiro que você passe o URL do arquivo de estilo pai também.

Eu criei um stackblitz básico mostrando onde estou acessando o CSS do componente pai: https://stackblitz.com/edit/angular-jhewzy

Arquivo CSS do componente pai (app.component.css) - Estou especificando a cor de plano de fundo da pmarca dentro do pai deve ser amarela. Eu quero herdar isso no componente filho.

p {
  background-color: yellow;
}

Abaixo está o CSS filho do componente (hello.component.css)

p {
  font-style: italic;
}

Como você deseja usar o componente pai dentro do componente filho, use o caminho do URL do estilo na propriedade styleUrls

import { Component, Input } from '@angular/core';

@Component({
  selector: 'hello',
  template: `<p>I am child</p>`,
  styleUrls: [`./hello.component.css`, './app.component.css'],
})


export class HelloComponent  {
  @Input() name: string;
}

Espero que ajude você.

PrinceIsNinja
fonte