How to apply CSS classes to another component in AngularDart?

angulardart ngstyle
_ngcontent
ng-deep
angular css class
component style
angulardart change detection
angular styles in @component
angular css example

Let's say there is a simple framework to display popups:

@Component(
  selector: 'popup-host',
  template: '''
      <div class="popup-container">
        <ng-template #popupRef></ng-template>
      </div>
  ''',
  styles: ['.popup-container { position: absolute; top: 100; left: 100; z-index: 100; }'],
)
class PopupContainerComponent {
  final PopupController _controller;
  final ComponentLoader _loader;

  PopupContainerComponent(this._controller, this._loader);

  void ngOnInit() {
    _controller.container = this;
  }

  @ViewChild('popupRef', read: ComponentRef)
  ComponentRef popupRef;

  void render(PopupConfig config) {
    final componentRef = _loader.loadNextTo(config.factory, popupRef);
    if (componentRef.instance is HasValueSetter) {
      componentRef.instance.value = config.value;
    }
  }
}

@Injectable()
class PopupController {
  PopupContainerComponent _container;
  set container(PopupContainerComponent container) => _container = container;

  void showPopup(PopupConfig config) {
    container.render(config);
  }
  ...
}

class PopupConfig {
  final ComponentFactory factory;
  final dynamic value;
  PopupConfig(this.factory, [this.value]);
}

abstract class HasValueSetter {
  set value(dynamic value);
}

This can then be used like this:

// Somewhere in the root template
<popup-host></popup-host>

// In popup.dart
@Component(
  selector: 'happy-popup',
  template: '''
      <div class="header">This is the popup content.</div>
      <div class="main">The value is {{value}}.</div>
      <div class="footer">I am happy!</div>
  ''',
)
class HappyPopupComponent implements HasValueSetter {
  @override
  dynamic value;
}

// In some_other.dart
@Component(
  ...
  styles: [
    '.header { font-weight: bold }',
    '.main { color: red }',
    '.footer { color: green; font-style: italic }',
  ],
  ...
)
class SomeOtherComponent {
  final PopupController _popupController;
  ...
  SomeOtherComponent(this._popupController, ...) ...;

  void displayPopup() {
    _popupController.showPopup(HappyPopupComponentNgFactory, 42);
  }
}
...

Is there a way to forward styles from <some-other-component> to <happy-popup> without having to define them at the root of the app?

Component Styles, Learn how to apply CSS styles to components. Use the function form :host() to apply host styles conditionally by including another selector inside parentheses� Class names and selectors are local to the component and don’t collide with classes and selectors used elsewhere in the app. Changes to styles elsewhere in the app don’t affect the component’s styles. You can co-locate the CSS code of each component with the Dart and HTML code of the component, which leads to a neat and tidy project

As your popup isn't a child of the component that opened it you cannot use ::ng-deep

the only thing I think that will work is to remove view encapsulation from the host, the popup and the component that opens the popup (try only the popup and component that opens the popup first, if that doesn't work, remove the host's encapsulation as well.)

@Component(
  selector: 'happy-popup',
  template: '''
      <div class="header">This is the popup content.</div>
      <div class="main">The value is {{value}}.</div>
      <div class="footer">I am happy!</div>
  ''',
  encapsulation: ViewEncapsulation.None // <=== no encapsulation at all
)
class HappyPopupComponent implements HasValueSetter {

Multiple Components, The component class name should be written in upper camel case and end in the word “Component”. The CSS selector name, my-hero , will match the element tag that identifies this Near the end of this tutorial page, you'll add a <my-hero> element to the You'll learn to create services in the next tutorial page. Master/� If you want to study W3.CSS, visit our W3.CSS Tutorial. Below is a complete HTML example, with all AngularJS directives and W3.CSS classes explained. HTML Code

Attribute Directives, Attribute directives—change the appearance or behavior of an element, component, class HighlightDirective { HighlightDirective(Element el) { el.style. But a component or directive shouldn't blindly trust other components and directives. Angular by default encapsulates component CSS. So lets take a look at the rendered output of our code so far. So we can see that each components corresponding .cmp CSS class is scoped to it’s own template. The default CSS behavior multiple .cmp classes would of caused global name collisions with our styles. So lets look at the Chrome dev

You can send prop value to component, which can be custom class and put it in your popop html. And then in scss file add extra css overrides for specific class. So for each custom component you can have custom css code.

PS: And yes, i would suggest to import scss file like:

@Component(
      styleUrls: ['./hero1.css'],
)

It is just better to seperate css from js + your css code then can be much longer, containing all styling cases.

Cheat Sheet, Binds the presence of the CSS class extra-sparkle on the element to the Component configuration, @Component extends @Directive , so the @Directive configuration applies to components as well Called before any other lifecycle hook. Angular 2 provide different ways to apply class to the elements based on certain conditions. In this post I would like to show you couple of ways to conditionally applying class to a DOM element in Angular 2 with ngClass. Methods to Apply CSS Classes Conditionally #1 #2 #3 #4

In addition to methods already mentioned I would suggest two more avenues to explore:

  1. since Angular scopes CSS to components and we'd like to keep it this way your crossing component boundary can be done by finding out what scope Angular assigned to it and adding manually scoped CSS into global <style> tag on the page:

    @ViewChild('popupRef') popupRef; ngAfterViewInit() { this.popupRef.nativeElement.attributes[0].name // this will have a value similar to _ngcontent-tro-c1 which you will need to scope all your custom CSS with. }

one apparent drawback of this approach is that Angular conceals CSS management and therefore you'll have to resort to plain JS to manage it. (one example here)

  1. you can try defining the CSS in @Component before creating it by utilising custom decorator factory like in this answer

Personally I'd explore the second option as it seems to be less hacky

Template Syntax, A template expression must not change any app state other than the You can add and remove CSS class names from an element's class� NgClass: How to assign CSS classes in Angular. In this tutorial, we are going to take a look how we can use CSS classes with angular. We will take a look at different methods to dynamically assign a CSS class to an element using the className directive.

Forms, Build an Angular form with a component and template. Provide visual feedback using special CSS classes that track the state of the controls. Temporarily add another template reference variable named spy to the Name <input> tag and� That means you can apply everything you know about CSS stylesheets, selectors, rules, and media queries directly to Angular applications. Additionally, Angular can bundle component styles with components, enabling a more modular design than regular stylesheets. This page describes how to load and apply these component styles.

Need a way for a component to add CSS classes to host non , In other situations, NgClass serves this purpose, but a component cannot apply a directive to its host element. Using the [class.whatever] syntax also doesn't solve � So far we’ve looked at adding just single classes, which is something the NgClass directive can also help us with as it supports multiple classes. Using multiple classes is the real reason to use the NgClass directive. You can think of NgClass as being able to specify multiple [class.class-name] on the same element.

AngularDart, One alterantive is to keep shadow DOM and change the CSS you applied to your Angular.dart supports to create components without shadow DOM by adding global styles, while being able to use global SASS code in each components? #import in your components it appends another copy to the main CSS file that� String – The CSS classes listed in the string (space-delimited) are added, Array – The CSS classes declared as the Array elements are added, Object – The keys are CSS classes that get added when the expression given in the value evaluates to the true value. If false, then they are removed.

Comments
  • Thank you. I was aware of the fact that I could separate stylesheets into a separate file, but didn't quite think about reusing them across multiple components. I am not sure if this solution is universal enough though, e.g. a popup component could be part of the framework and importing parts of the app into the framework may be contrary to good software practices. Ideally, framework would provide a way to import an arbitrary css file provided via the PopupConfig. Is it possible to customize the styleUrls property on a component at run-time?
  • Also what if there are multiple components that want to open the same popup, but style it differently?
  • Yes you can set the styleUrls dynamically at the run-time. There are multiple ways to do it. I suggest you to search for Angular dynamic styleUrls to get some ideas and see which one fits you the best. Regarding the second question. If that's the case, I would import the shared popup styling file + the styling file where I overwrite the styles I want to change for a specific component.
  • I an not sure I understand your suggestion on how to style two popups differently. Both popups would use the same component, so the only way I can overwrite the styles from a shared file is by appending a new entry to styleUrls at run-time, isn't it? What if two popups appear at the same time, e.g. one opens another, and need to by styled differently? If I modify the styleUrls, wouldn't it style both? Finally, I couldn't find a good article on how to dynamically modify styleUrls without hacks. It seems to be not supported by Angular natively.
  • Can you please explain what you mean by "remove view encapsulation"?
  • @SergiyBelozorov Done :). let me know if it helped you
  • It certainly helped me learn something new about Angular and how one can configure components :-), but I am not sure this is the best approach. With generic class names such as header, main, and footer one can easily style such components incidentally. Perhaps one can try to use more specific names to avoid conflicts, but I would prefer a solution that does keep the encapsulation.
  • I understand your concern but that’s the only solution to your requirements. As you said one can try to use more specific name and classes, maybe use the BEM approach
  • Disabling ViewEncapsulation is a big no-no for mid or large sized applications. It takes special care or your whole styling will get messed up in a long run. (ex: generic class names). And I disagree that it's the only solution to his requirements.
  • Yes, we do indeed use scss and @import statements. But just like the answer from @Dino, I wonder if it's possible to not have to hard-code the style URL into the popup component, but read it from the PopupConfig and somehow assign it at run-time?