Angular Material 2 Spinner with Angular 4

Viewed 8844

With the help of existing angular material tutorial on coursetro, I was able to try http and subscribe scenarios with Angular 4 & Angular Material controls. As i was fetching all the photos at first place I see a lag in UI. Hence I've thought of implementing Spinner which gives impression of loading of data md-progress-spinner, but for some reason spinner doesn't show up & moreover I don't see any console logs too, Could you please advise?

spinner.service.ts:

import {Injectable} from '@angular/core';
import {Subject} from 'rxjs/Subject';


@Injectable()
export class SpinnerService {
    public status: Subject<boolean> = new Subject();
    private _active: boolean = false;

    public get active(): boolean {
        return this._active;
    }

    public set active(v: boolean) {
        this._active = v;
        this.status.next(v);
    }

    public start(): void {
        this.active = true;
    }

    public stop(): void {
        this.active = false;
    }
}

app.module.ts:

@NgModule({
    declarations: [
        AppComponent,
        SpinnerComponent
    ],
    imports: [
        BrowserModule,
        FormsModule,
        HttpModule,
        BrowserAnimationsModule,
        MdButtonModule,
        MdMenuModule,
        MdCardModule,
        MdToolbarModule,
        MdIconModule,
        MdProgressSpinnerModule
    ],
    providers: [SpinnerService],
    bootstrap: [AppComponent]
})
export class AppModule { }

app.component.ts:

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    myData: Array<any>;

    constructor(private http:Http,private spinner: SpinnerService) {
        this.spinner.start();
        this.http.get('https://jsonplaceholder.typicode.com/photos')
                 .map(response => response.json())
                 .subscribe(res => this.myData = res,
                            error => console.error(error),
                            () => this.spinner.stop()
                           );
     }
}

app.component.html:

<app-spinner>Spinning...</app-spinner>

<md-toolbar color="primary">

    <span>MyCompany</span>
    <span class="example-spacer"></span>
    <button md-button [mdMenuTriggerFor]="appMenu"><md-icon>menu</md-icon> Menu</button>

</md-toolbar>

<md-menu #appMenu="mdMenu">
    <button md-menu-item> Settings </button>
    <button md-menu-item> Help </button>
</md-menu>

<md-card class="example-card" *ngFor="let data of myData; let i = index">

    <!--<md-card class="example-card" *ngFor="let data of (myData ? myData.slice(0,10): []); let i = index"> -->

    <img md-card-image src="{{ data.url }}">
    <md-card-header>
        <md-card-title>{{ data.title }}</md-card-title>
    </md-card-header>

    <md-card-actions>
        <button md-button>LIKE</button>
        <button md-button>SHARE</button>
    </md-card-actions>
</md-card>

spinner.component.ts:

 @Component({
     selector: 'app-spinner',
     templateUrl: './spinner.component.html',
     styleUrls: ['./spinner.component.css']
 })
 export class SpinnerComponent implements OnInit, OnDestroy {

     public active: boolean;

     public constructor(private spinner: SpinnerService) {
         spinner.status.subscribe((status: boolean) => {
             this.active = status;
         });
     }

     ngOnInit(){
         this.spinner.stop(); // or do it on some other event eg: when xmlhttp request completes loading data for the component
     }

     ngOnDestroy(){
         this.spinner.start();
     }

 }

spinner.component.html:

 <div *ngIf="active">
     <md-progress-spinner mode="indeterminate"></md-progress-spinner>
 </div>

Please check if I've made any errors in loading the spinner and my vision is to have this spinner used across multiple components within multiple subscribing calls by having the app-spinner selector mentioned in only app.component.html, could you please advise if above approach holds good & any changes required?

3 Answers

I got the spinner elements in the DOM, but I couldn't see it, this is the way I solved:

In html component:

<mat-progress-spinner mode="indeterminate" [diameter]="28"></mat-progress-spinner>

In app.module.ts:

import { MatProgressSpinnerModule } from '@angular/material';
@NgModule({
  imports: [
    MatProgressSpinnerModule],
  exports: [
    MatProgressSpinnerModule
  ]

and in style.css:

@import '~@angular/material/prebuilt-themes/deeppurple-amber.css';
Related