How can I dynamically reference two template HTML files (one for mobile and one for desktop) within a single component in Angular 6?

Here is the approach I have taken.

Organizational structure

mobile-view.component.html

<p> This content is for mobile view </p>

desktop-view.component.html

<p> This content is for 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 method, all main logic and binding variables are kept in base.component.ts file

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

Note:- This code example is just a demonstration of what I have attempted.

Requirement :

  1. An AOT build is required.
  2. If there is a better approach or standard practice for achieving this?

  3. If there is a way to set the template dynamically based on the device that made the request. Refer to the code in base.component.html constructor for code to fetch userAgent information (provides info about the device making the request), which I am currently using.

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. This approach resulted in an AOT build failure
  2. and the use of function call in the component decorator is deprecated

Answer №1

Here is a simpler approach compared to the one mentioned above. By using ngContainer with ngTemplateOutlet, you can dynamically inject templates into containers based on conditions.

@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();
     }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Transmitting data from Angular to .NET Core for seamless integration

I have been attempting to send an xls or any other file from my angular application to a .NET core controller, but none of my methods seem to work... Below is my component where I call my service upon button click: handleFileInput(file: FileList) { this. ...

A guide on transforming a string into an array of objects using Node.js

Hey everyone, I have a single string that I need to convert into an array of objects in Node.js. let result = ""[{'path': '/home/media/fileyear.jpg', 'vectors': [0.1234, 0.457, 0.234]}, {'path': '/home/med ...

Deciphering the intricacies of AWS-Config Rules and Alterations in Configuration

Currently, I am utilizing the aws-cdk to create config rules for approximately 15 rules that we need to monitor and receive notifications on. Below is a snippet of the code for reference: // Code snippet showing the creation of multiple config rules My m ...

The separator falls short of spanning the entire width of the page

For some reason, I can't seem to make the divider extend to the full length of the page. <TableRow> <TableCell className={classes.tableCell} colSpan={6}> <Box display="grid" gridTemplateColumn ...

Accessing route parameters in Angular directly from the templateFinding route parameters in

There are times when my routes have multiple parameters like: /checklists/:type/:view/:filter I want to generate links in the template in this manner: <a routerLink="['/checklists',':type',':view',':filter']"> ...

Setting up Microsoft Clarity for your Angular app on localhost is a simple process

Currently, I am attempting to set up Microsoft Clarity on my Angular app to run on localhost. After creating a new project on the Microsoft Clarity portal and specifying the URL as localhost (I also tried using localhost:4200</code), I copied the scrip ...

Generate an auto-focus Power BI report seamlessly and effortlessly

I'm working on a straightforward Microsoft Power BI example that showcases a list of employees grouped by gender. <iframe width="300" height="200" src="https://app.powerbi.com/view?r=******" ></iframe> The issue I am facing is that the ...

Vue 4 and TypeScript: Dealing with the error message 'No overload matches this call'

In my Vue-Router 4 setup, I am trying to combine multiple file.ts files with the main vue-router (index.ts) using TypeScript. However, it throws an error that says "TS2769: No overload matches this call. Overload 1 of 2, '(...items: ConcatArray[]): ne ...

Linking to a variable that could potentially be non-existent

How can I properly bind to myVariable even if it may not be present? (myVariable comes from a service that may not always be active) <input pInputText type="text" [size]="size" [value]="myVariable" style="cursor: poin ...

Angularjs and Angular (5) routing combo

I'm currently exploring the possibility of running angular alongside our existing angularjs application. Instead of immediately diving into the tedious process of transitioning to ngUpgrade, I wanted to attempt running them independently first. My ide ...

An issue has been encountered: No NgModule metadata was discovered for 'AppModule' in the ngx-rocket Metronic theme

Task List [ ] Initialize [x] Build [x] Serve [ ] Test [ ] End-to-End test [ ] Generate [ ] Add [ ] Update [ ] Lint [ ] Internationalization [ ] Run [ ] Configure [ ] Help [ ] Version [ ] Documentation Is this a regression? This issue started occurring ...

How can a TypeScript Angular directive utilize a function?

Recently, I have been following a unique Angular directive TypeScript pattern that I find really effective. The approach involves giving the directive its own isolated scope by creating a new controller. I encountered a scenario where I needed to invoke a ...

Dynamically set the value of a form in <mat-select> using binding

In my 'div' element, I have implemented a "mat-select" feature that contains a dropdown of country lists in a multi-select format. I am looking to automate the process of populating the countries within the "mat-select" when a button is clicked. ...

Route protection is ineffective when dealing with two observables simultaneously

After writing the route guard as shown below, I encountered an issue with the else statement that was not returning a result, even though it should have. Surprisingly, there were no errors either. this.hotelSettingsService.get().pipe(map(res => { ...

Troubleshooting Angular modal fade not functioning

I am facing an issue while trying to display a component called "Login", which belongs to the class "modal fade", from another component named "navbar". Despite my attempts to trigger it by calling data-bs-toggle="modal" data-bs-target="#LoginModal" from t ...

Angular2 Components with Unique Styling

I am working on an Angular2 app that includes several components, some of which I want to reuse multiple times on a single page. Instead of having three separate components, I am looking to refactor and combine their functionalities into one. The basic st ...

Tips for effectively handling the auth middleware in react.js by utilizing LocalStorage

After making a call to the authentication API, the plan is to save the authentication token in LocalStorage and then redirect to a dashboard that requires token validation for entry. However, an issue arises where the authentication token isn't immedi ...

Sign in to Azure for an Angular application within the iFrame of another Angular application

I have two separate Angular apps, both enabled with Azure AD login. When accessed separately in the tab, they function properly - redirecting and obtaining the token without issue. Now, I aim to make Angular 1 the Parent and Angular 2 the child within a s ...

Guide to displaying the continent name on a 3D globe using Reactjs, TypeScript, and Threejs

I am currently working on integrating Threejs into my Nextjs 14 application to create a 3D earth globe using Gltf. However, I am facing an issue where I am unable to display the text of the continent name on their respective continents. I want to have fixe ...

What is causing the issue with using transition(myComponent) in this React 18 application?

Recently, I have been immersed in developing a Single Page Application using the latest version of React 18 and integrating it with The Movie Database (TMDB) API. My current focus is on enhancing user experience by incorporating smooth transitions between ...