NEERAJ VAGEELE
NEERAJ VAGEELE

Reputation: 21

How to refer 2 template html file (mobile and desktop) dynamically in single component in angular 6?

My approach is as below.

Folder structure

mobile-view.component.html

<p> this is mobile view</p>

desktop-view.component.html

<p> this is desktop view</p>

mobile.component.ts

import { BaseComponent } from './base.component';

@Component({
    selector: 'app-mobile-view',
    templateUrl: './mobile-view.component.html'
})

export class MobileComponent extends BaseComponent { }

desktop.component.ts

import { BaseComponent } from './base.component';

@Component({
    selector: 'app-desktop-view',
    templateUrl: './desktop-view.component.html'
})

export class DesktopComponent extends BaseComponent { }

base.component.ts

@Component({
   selector: 'app-root',
   template: `<app-mobile-view *ngIf="isMobileView"></app-mobile-view>

    <app-desktop-view *ngIf="!isMobileView"></app-desktop-view>`
})
export class BaseComponent implements {

   isMobileView: boolean;

   constructor(){
        if (navigator.userAgent &&
           (navigator.userAgent.match(/Android/i) ||
           navigator.userAgent.match(/webOS/i) ||
           navigator.userAgent.match(/iPhone/i) ||
           navigator.userAgent.match(/BlackBerry/i) ||
           navigator.userAgent.match(/Windows Phone/i))) {

           this.isMobileView = true;
        } else {
           this.isMobileView = false;
        }
   }

   ngOnInit() {
    // code
   }

   // various methods
}

In this approach my main logic and all binding variables reside in base.component.ts

Mobile component and Desktop component extends Base component to access all methods and variables

Note:- This is demo code just for understanding what i have tried.

Requirement :

  1. AOT build is must.
  2. Need any better approach or standard practice for achieving this

  3. Need a way to set template dynamically based on device from which it is request. Refer base.component.html constructor for code of getting userAgent(provide info of device from which request is comming) which i am using currently.

Previous method used:-

main.component.html

@Component({
   selector: 'app-root',
   template: function () {
     if (isMobileUser()) {
            return require('./mobile-view.component.html');
       } else {
            return require('./desktop-view.component.html');
       }
     }(),
    styleUrls: ['./main.component.scss']
})

export class MainComponent {
}
  1. In this approach AOT build is failing
  2. function call in component decorator is deprecated

Upvotes: 2

Views: 410

Answers (1)

Suresh Kumar Ariya
Suresh Kumar Ariya

Reputation: 9764

You can follow this approach which is simpler when compared to above one. using ngContainer with ngTemplateoutlet, you can inject the template into the container based on condition.

@Component({
    selector: 'app-mobiledesktop-view',
    templateUrl: './mobiledesktop-view.component.html'
})

export class MobileDesktopComponent { }


**Template:**

<ng-template #mobileView>
  This is mobile view
</ng-template>

<ng-template #desktopView>
  This is desktop view
</ng-template>

<ng-container *ngTemplateOutlet="isDesktop ? desktopView : mobileView">

</ng-container>

Using Dynamic Component:

@Component({
    selector: 'app-desktop-view',
    template: 'This is desktop view'
})

export class AppDesktopComponent { }

@Component({
    selector: 'app-mobile-view',
    template: 'This is mobile view'
})

export class AppMobileComponent { }

@Component({
    selector: 'app-container-view',
    template: ' <ng-container #messagecontainer></ng-container>'
})

export class AppContainerComponent { 
     private componentRef;
     @ViewChild('messagecontainer', { read: ViewContainerRef }) entry: ViewContainerRef;
     constructor(private resolver: ComponentFactoryResolver) { }

     ngAfterViewInit(){
        const component = (isDesktop) ? AppDesktopComponent : AppMobileComponent;
        const factory = this.resolver.resolveComponentFactory(component);
        this.componentRef = this.entry.createComponent(factory);
        //this.componentRef.instance.data = appData;
     }

     ngOnDestroy() {
        this.componentRef.destroy();
     }
}

Upvotes: 1

Related Questions