angular / angular

Deliver web apps with confidence 🚀
https://angular.dev
MIT License
96.08k stars 25.42k forks source link

Interpolation options for View.styles argument #7251

Closed Hedde closed 3 years ago

Hedde commented 8 years ago

I have an app that requires the overloading of some stylesheet properties. A use-case example:

In my opinion I should be able to interpolate the styles argument just like templates, taken the angular.io website example, something like this:

@Component({
      selector: 'todo-app',
      template: '<span>{{todos.length}}</span>',
      styles:['a { color: {{styles.someAttr}}; }'],
      directives: [TodoList, TodoForm]
})
export class TodoApp {
      // retrieve and set styles variable from a service
}

Please note that these styles should be applied globally and are received in a dynamic fashion (from a service that outputs json for example).

Sofar I have been unable to find a proper hook to interpolate the styles argument or render style sheets overall. Please advise.

zoechi commented 8 years ago

Seems to be a dup of #6274

Hedde commented 8 years ago

@zoechi that post doesn't really hold an answer for global styles and/or rendering style sheets with variables. It uses ngStyle on a single element which is not what I'm trying to achieve, let alone a DRY solution.

zoechi commented 8 years ago

I didn't say it holds an answer. I just think the reported issues are quite similar. The suggestion to use NgStyle is common for this kind of feature request. I also don't think it's a substitute.

souldreamer commented 8 years ago

The only solution I've managed to put together is quite a bit buggy, as apparently Angular doesn't remove <style>s inserted into the <head> when destroying a component whose encapsulation is ViewEncapsulation.None (needed to make the styles global).

You can see a demo of it in this codepen

Basically, I created a component <global-style> which creates a dynamic component with the input style whenever the input style changes. Don't change the input style too often though, or you'll get more and more <style> tags in the page. Still searching for a fix for that (that doesn't directly access the DOM :D )

@Component({
  selector: 'global-style',
  template: '',
  changeDetection: ChangeDetectionStrategy.OnPush
})
class GlobalStyleComponent implements OnChanges {
  private _style: string;
  @Input()
  set style(value: string) {
    this._style = value;
    this.constructStyles();
  }
  get style(): string {
    return this._style;
  }

  private _currentStyleComponent: ComponentRef = null;

  constructor(private _dynamicComponentLoader: DynamicComponentLoader, private _viewContainerRef: ViewContainerRef) {
  }

  constructStyles() : void {
    if (this._currentStyleComponent) this._currentStyleComponent.destroy();

    let styles = this.style;
    @Component({
      selector: 'style-component',
      template: '',
      encapsulation: ViewEncapsulation.None,
      styles: [styles]
    })
     class StyleComponent {
    };

    this._dynamicComponentLoader.loadNextToLocation(StyleComponent, this._viewContainerRef).then(component => this._currentStyleComponent = component);
  }
}

Use it like:

<global-style style="* {color: red}"></global-style>

or

<global-style [style]="someStyleVariable"></global-style>

Edit: Sorry for resurrecting this, just saw the dates on the posts now.

rizwanhussain-vteams commented 8 years ago

Any update on this?

vinayakpatil commented 7 years ago

+1

Frimlik commented 3 years ago

Any update on this issue? My problem is that I need to load settings from external config file (that can vary according to customer and thus needs to be loaded dynamically) and have a plenty of styling stuff, e.g. colours and header pictures for each subpage. I'd like to have this stuff in one place = in one (s)css file under certain class selectors, not to set ngStyle for each element. And in addition to be able to use these styles throughout whole application, that means usage of ViewEncapsulation.None.

<style>
  .container .headerX {
    bacgroundPicture: url({{pathToSectionXHeaderPicture}});
    color: {{sectionXColor}};
  }
  .container .sectionX {
    bacgroundColor: {{sectionXBgColor}};
    color: {{sectionXColor}};
  }
  .container .headerY {
    bacgroundPicture: url({{pathToSectionYHeaderPicture}});
    color: {{sectionYColor}};
  }
  .container .sectionY {
    bacgroundColor: {{bgSectionY}};
    color: {{sectionYColor}};
  }
</style>`

Is this possible?

Thanks

angular-robot[bot] commented 3 years ago

Just a heads up that we kicked off a community voting process for your feature request. There are 20 days until the voting process ends.

Find more details about Angular's feature request process in our documentation.

angular-robot[bot] commented 3 years ago

Thank you for submitting your feature request! Looks like during the polling process it didn't collect a sufficient number of votes to move to the next stage.

We want to keep Angular rich and ergonomic and at the same time be mindful about its scope and learning journey. If you think your request could live outside Angular's scope, we'd encourage you to collaborate with the community on publishing it as an open source package.

You can find more details about the feature request process in our documentation.

alxhub commented 3 years ago

Closing this as infeasible - Angular styles are per-component, not per-instance, so interpolations within the style text are not possible under the current architecture. I suspect that repeatedly changing a stylesheet is also likely to incur a significant performance penalty.

angular-automatic-lock-bot[bot] commented 3 years ago

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.