Подтвердить что ты не робот

Стиль расширения/переопределения компонента многократного использования angular2

Предполагая, что мы хотим использовать компонент из некоторой библиотеки в angular2 (пример из material2). Компонентная аннотация выглядит следующим образом:

@Component({
  moduleId: module.id,
  selector: 'md-input',
  templateUrl: 'input.html',
  styleUrls: ['input.css'],
  providers: [MD_INPUT_CONTROL_VALUE_ACCESSOR],
  host: {'(click)' : 'focus()'}
})

Этот компонент поставляется с таблицей стилей по умолчанию "input.css". Если мы используем этот компонент в нашем приложении, мы, вероятно, захотим переопределить/расширить часть стиля, не копируя и не манипулируя самим компонентом. Как это сделать?

Возможное решение 1: Установите инкапсуляцию на "ViewEncapsulation.None":
На самом деле это не решение, просто обходной путь.

Возможное решение 2: Используйте ":: shadow" или "/deep/" в CSS:
Также работает, но его устарело в соответствии с спецификацией WebComponent.

Возможное решение 3. Используйте глобальный CSS и переопределите компонент CSS:
Работает также, но это нарушает концепцию тени DOM.

Возможное решение 4: переопределить непосредственно в шаблоне родительского компонента:

Пример:

<my-cmp [font-size]="100"></my-cmp>

Не подходит, если мы много переопределяем.

Возможное решение 5: переопределить или расширить определение "@Component" с помощью дополнительной таблицы стилей:
Кажется, это единственное правильное решение (по крайней мере для меня). Но я не знаю, как это сделать...

Любые советы по этому поводу? Может, у меня что-то не так... Спасибо.

4b9b3361

Ответ 1

Для решения 5 вам необходимо создать подкласс для целевого компонента, создать пользовательский декоратор, который обрабатывает/переопределяет метаданные и устанавливает его для текущего подкомпонента.

Вот пример:

@CustomComponent({
  styleUrls: ['css/style.css']
})
export class OverridenComponent extends SomeComponent {
}

Декоратор CustomComponent будет выглядеть так:

export function CustomComponent(annotation: any) {
  return function (target: Function) {
    var parentTarget = Object.getPrototypeOf(target.prototype).constructor;
    var parentAnnotations = Reflect.getMetadata('annotations', parentTarget);

    var parentAnnotation = parentAnnotations[0];
    Object.keys(parentAnnotation).forEach(key => {
      if (!isPresent(parentAnnotation[key])) {
        annotation[key] = parentAnnotation[key];
      }
    });
    var metadata = new ComponentMetadata(annotation);

    Reflect.defineMetadata('annotations', [ metadata ], target);
  }
}

См. этот вопрос для получения дополнительной информации:

Ответ 2

Начиная с Angular 2.3, мы можем использовать наследование компонентов. Чтобы выполнить решение 5, мы могли бы это сделать.

//This is our base component that we want to override
@Component({
  selector: 'pagination',
  templateUrl: './pagination.component.html',
  styleUrls: ['./pagination.component.css']
})
export class PaginationComponent {
}


//This inherits from our base component and uses a different style sheet.
@Component({
  selector: 'pagination2',
  //This is sharing the template with the parent class.  Note
  //this needs to be included since templateUrl doesn't automatically
  //inherit.
  templateUrl: './pagination.component.html',
  //This is using a unique css file 
  styleUrls: ['./pagination2.component.css']
})
export class PaginationComponent2 extends PaginationComponent {
}

Ответ 3

Возможное решение 2: Используйте ":: shadow" или "/deep/" в CSS:

Это применимо только в том случае, если вы используете ViewEncapsulation.Native.

Если вы используете ViewEncapsulation.Emulated (по умолчанию), то Angular использует его собственную интерпретацию /deep/ и ::shadow, а устаревание не применяется.

Если вы используете ViewEncapsulation.Native, тогда вам пока что не повезло, потому что устаревшие браузерные ::shadow и /deep/ глубоко устарели, а Angular еще не предоставил поддержки для поддержки тем для ViewEncapsulation.Native, как для пример. Полимер делает с (полифильмированными) переменными CSS и миксинами.

Ответ 4

В Angular 4 мы можем переопределить стиль с помощью селектора псевдо-класса ::ng-deep из таблицы стилей унаследованного класса.

:host ::ng-deep element {
    //your style here
}

Для получения дополнительной информации см. http://blog.angular-university.io/angular-ngclass-ngstyle/