Benjamin Geese
Benjamin Geese

Reputation: 35

Angular 1.5 components and ui-router 1.0: Add attributes to inserted dom element

In Angular 1.5, the .component() was introduced and seems to be considered good practice. I am currently migrating to ui-router 1.0 which allows (and recommends) routing to components. So I refactored a controller/template route to a component router which works great: The component "example" gets injected to the ui-view container in its own DOM node:

However that breaks my layout (using angular material). The workaround i used is simply copying and using css classes angular material uses for layout on the inserted node. However, i consider this a "hacky" solution: What if angular material changes it's layout module for example?

A better solution would be to add layout attributes or even a css class to the "example" element. But how can i do that? Is that even possible?

I think this question is related to the following, where i provided a workaround for the specific problem. But I am interested in a more generic solution: Using angular component breaks material layout

Upvotes: 3

Views: 463

Answers (1)

Peter Alexay
Peter Alexay

Reputation: 91

I faced the same problem in my Angular 1.5 project where I also use angular-ui-router and Angular Material components. One possible solution is simply using string-based binding where you bind two attributes into your component: layout and flex. You can give the values for these two bound attributes (usually 'row' and '100' respecively) as you specify your ui-routing state in the following way:

var exampleState = {
    name: 'examplestate',
    url: '/',             // change this to your desired path
    component: 'example',
    resolve: {
        layout: function () {
            return 'row'; // you can change this value depending on your UI requirements
        },
        flex: function () {
            return '100'; // you can change this value depending on your UI requirements
        }
    }
};

In the config method of your module, you define your exampleState in the standard way:

$stateProvider.state(exampleState);

Finally, in the component definition, as you define your bindings, you add these two attributes to the list of bound attributes. Example in Typescript:

export class ExampleComponent implements ng.IComponentOptions {

    public bindings: any;
    public controller: any;
    public template: string;

    constructor() {
        this.bindings = {
            layout: '@',
            flex: '@'
        };
        this.controller = ExampleComponentController;
        this.template = ExampleViewTemplate;
    }
}

You can add this component to your angular module in the usual way:

.component('example', new ExampleComponent());

This will result in the following HTML element in the DOM (created by angular-ui-router automatically):

<example layout="row" flex="100" class="ng-scope ng-isolate-scope layout-row flex-100">

So in this way you don't need to insert any manual CSS styling in your code. You are using the standard Angular Material attributes on your component-element.

Upvotes: 3

Related Questions