Как решить проблему View Encapsulation в Angular8? - PullRequest
8 голосов
/ 03 марта 2020

У меня есть родительский компонент и дочерний компонент. Дочерний компонент создан как модальный компонент. Поэтому я включил селектор дочернего компонента в родительский компонент, и я установил инкапсуляцию представления, равную none, чтобы он принимал родительский компонент css, и все, и это тоже работает, но у родительского компонента есть #paper id, применяющий какую-то третью сторону (rappid js ) библиотека css (для построения диаграмм SVG). Так же, как дочерний компонент имеет идентификатор #dataMapper. но здесь третья сторона css не принимает, потому что дочерний компонент установлен на 'encapsulation: ViewEncapsulation.None'. Если я удалю encapsulation: ViewEncapsulation.None, это работает, но модальное не работает. загрузка всех модалов вместо onclick. Как решить эту проблему, пожалуйста, посоветуйте мне кого-нибудь.

Кодирование:

Родительский компонент TS

@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

<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

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

Дочерний компонент Ts

@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');
  }

}

Модальный код обслуживания

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();
  }
}

Пожалуйста, дайте мне знать, если требуется более подробная информация.

Ответы [ 2 ]

1 голос
/ 10 марта 2020

Из-за вашего модальности. Модал создается в top вашего приложения (из тега body, если вы ищите модальную обертку , проверяя ит.)

Это модал, потому что структура dom не совпадает c со структурой компонентов ng

Так почему модал работает с ng Encapsulation? Потому что ваш модальный сервис может справиться с этим.

Но сторонний CSS файл не является частью вашей angular конфигурации компиляции (т.е. работает только sass, s css). Поэтому он игнорирует все .css, даже если вы импортируете его правильно.

Чтобы решить эту проблему, вы можете применить. css в глобальном масштабе. Или, если вы боитесь, что может перезаписать других глобальных стилей, вы можете переименовать файл css в '_somefile.s css' (обратите внимание на da sh '_', это важно.)

Затем в вашем проекте global style.s css file> create селектор соответствует вашей модальной оболочке> под селектором: добавьте строку, которая @import somefile (не добавляйте расширение)

style.s css

.modal-wrapper {
    @import somepath/somefile
}
0 голосов
/ 08 марта 2020

Как вы описали в проблеме, вы хотите наследовать css родительского компонента внутри дочернего компонента. Итак, я предполагаю, что у вас есть одинаковые HTML элементы в родительских и дочерних компонентах, и вы не хотите дублировать вашу css.

, так как мы не можем повторить вашу проблему, и у вас нет создал любой экземпляр стекаблица. Я бы предложил лучшую альтернативу, которая будет работать. Найдите его ниже:

Мы можем указать несколько CSS URL-адресов внутри свойства styleUrls объекта метаданных @Component decorator. Итак, я бы посоветовал вам также передать родительский файл стиля Url.

Я создал базовый c stackblitz, показывающий, где я получаю доступ к CSS родительского компонента: https://stackblitz.com/edit/angular-jhewzy

Родительский компонент css файл (app.component. css) - Я указываю цвет фона тега p внутри родительского элемента должен быть желтым. Я хочу наследовать это в дочернем компоненте.

p {
  background-color: yellow;
}

Ниже дочерний компонент CSS (hello.component. css)

p {
  font-style: italic;
}

Как вы хотите использовать родительский компонент внутри дочернего компонента просто используйте URL-адрес стиля в свойстве 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;
}

Надеюсь, это поможет вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...