devidove
devidove

Reputation: 125

How apply styles from Material Angular

I need to add a button with the Material Angular 2 style. So I have a button that does this:

<button mat-button (click)="addElement($event, 'button')">Add button</button>

Where addElement is defined:

addElement(ev, tag) {
    const htmlElem = ev.currentTarget;
    const el = this.renderer.createElement(tag);
    this.renderer.setAttribute(el, 'mat-button', '');
    el.textContent = 'New Button';

    htmlElem.parentNode.insertBefore(el, null);
  }

Clicking on the button then creates a new element in my HTML, shown as:

<button mat-button">Add button</button>

The function code correctly generates the button, however it doesn't apply all children as shown in the original button code from the material code

So do I have a way to "refresh" the button so that the everything from the standard Mat-button applies to the button added via the JS code?

Upvotes: 2

Views: 1046

Answers (2)

davecar21
davecar21

Reputation: 2674

What went wrong?

You are right that you have added the mat-button attribute but since you are creating a button dynamically you did not be able to achieve to generate the whole structure of mat-button.

Below is the whole style and structure of mat-button

<button class="mat-button" mat-button="">
<span class="mat-button-wrapper">Add button</span>
<div class="mat-button-ripple mat-ripple"></div>
<div class="mat-button-focus-overlay"></div>
</button>

As you can see there are other html elements in the mat-button which includes ripple effects and focus overlay.


The Solution to your question

We are going to use Angular Renderer to create html element, set the attribute to the element and to append it on an element.

So what we did

create the button that will trigger the append

<button id="clickBtn" (click)="onClick()">Click here to add Button</button>

import the import Directive, ElementRef, Renderer2 in the component.

{ Component, Directive, ElementRef, Renderer2 } from '@angular/core';

add a directive that will target the html element where the button will get appended (#clickBtn [is the id tag of the button that we created)

@Directive({ 
     selector: '#clickBtn' 
})

create a constructor to inject renderer and elementref

constructor(private renderer: Renderer2,private elRef: ElementRef)   { 

}

trigger the click event to append the button

    onClick() {
     const btn = this.renderer.createElement('button');
     const span = this.renderer.createElement('span');
     const div1 = this.renderer.createElement('div');
     const div2 = this.renderer.createElement('div');

     const text = this.renderer.createText('I am a Generated Button');

     const attrBtn = this.renderer.setAttribute(btn, 'class', 'mat-button');
    const attrSpan = this.renderer.setAttribute(span, 'class', 'mat-button-wrapper');
    const attrDiv1 = this.renderer.setAttribute(div1, 'class', 'mat-button-ripple mat-ripple');
    const attrDiv2 = this.renderer.setAttribute(div2, 'class', 'mat-button-focus-overlay');

     this.renderer.appendChild(span, text);
     this.renderer.appendChild(btn, span);
     this.renderer.appendChild(btn, div1);
     this.renderer.appendChild(btn, div2);
     this.renderer.appendChild(this.elRef.nativeElement, btn);
   }

Woah so what going on here. as you can see we generate here all the structure of the mat-button

To know more about Renderer2 Please visit this link.

https://alligator.io/angular/using-renderer2/


Please see the link of live code on stackblitz

https://stackblitz.com/edit/dmgrave-ng-so-answer-dom?file=app%2Fapp.component.ts

Hope this helps.

Upvotes: 2

brijmcq
brijmcq

Reputation: 3418

I'm not sure why you want to generate the buttons dynamically but I would do it something like this

In your template:

<button mat-raised-button (click)="addNewButton()">Add new </button>
<div  *ngFor="let btn of buttonsList">
<button mat-raised-button color="primary">
  {{btn+1}}
</button>
</div>

In your component:

export class AppComponent  {
  buttonsList = [];

  addNewButton():void{
    const newId = this.buttonsList.length;
    this.buttonsList.push(newId);
  }
}

You just have to loop through your array and display the buttons. Every time you add a new button, you just have to push a new value to your array and let the framework do the heavy lifting.

Here's the stackblitz demo : https://stackblitz.com/edit/angular-7rfwrx?file=app%2Fapp.component.ts

Hope this helps.

Upvotes: 1

Related Questions