6

In the application i am developing, it needs entirely two different views for Desktop and Mobile. Not possible using CSS as content is entirely different.

What I have done?

I had checked whether it is Desktop/Mobile in Routing file using code const isMobile = window.innerWidth < 768;

And in path component: component: isMobile ? MobileComponent : DesktopComponent

This is working perfectly in development environment. But while production build this fails ng serve --prod (obviously Angular 5)

Issue:

No errors at all, According to isMobile true/false it should load MobileComponent/ DesktopComponent. But it does not load even if isMobile is true/false

Always loads MobileComponent in both Desktop & Mobile. while isMobile value is getting calculated correctly, true for Mobile and false for Desktop

I think the reason is the routes are getting compile already before sending to client.

Workaround tried but not working:

Used a if..else condition, while calculating isMobile and giving that variable (component) instead of ternary operation in Routing file

Any way:

Is there any way I can use to achieve the same functionality?

Thanks in advance

zgue
  • 3,417
  • 9
  • 31
  • 35
Harikrishnan N
  • 704
  • 9
  • 18

4 Answers4

7

As I said in the question comment section, route guards would be a good solution for this purpose.

The MobileGuard would look like this :

export class MobileGuard implements CanActivate {
    constructor(private _router: Router, private _mobileService: MobileService) {}

    canActivate(): boolean {
        const isMobile = this._mobileService.isMobile();
        if(!isMobile) {
            this._router.navigate(['/desktop']);
        }
        return isMobile;
    }
}

The same for the DesktopGuard.

The user trying to access any of the routes, would be redirected to the right one.

Here is a running example with this suggested solution.

And here is the stackblitz editable version.

ibenjelloun
  • 6,040
  • 2
  • 17
  • 44
4

Don't use canActivate or route guards, because they need to be used for authentication etc.

New way:

{
    path: 'your-path',
    loadChildren: () => {
      if(window.innerWidth > 768 ) {
        return import('./your-desktop.module').then(m => m.YourDesktopModule)
      } else {
        return import('./your-mobile.module').then(m => m.YourMobileModule)
      }
    }
}
Suraj Rao
  • 28,186
  • 10
  • 88
  • 94
CarbonDry
  • 762
  • 1
  • 10
  • 23
1

Directly make changes in the routes like this -

const routes: Routes = [{
  path: '',
  component:  window.screen.width > 767 ? WelcomeDesktopComponent : WelcomeMobileComponent
}];

Vivek Kumar
  • 1,073
  • 2
  • 12
  • 21
0

I agree with @CarbonDry that using a logic in your RoutingModule is the best way. However I think using window size is a poor way to detect device type. Of course, it depends on the use case - if you simply need to show different UI for small screens, window.innerWidth will do. If you want separate functionality for mobiles, it might not be just enough.

There are various ways you could check for device type, for example you can use navigator.orientation === undefined to check if a device is desktop (because desktops do not support navigator.orientation.

Lastly, you could always use UserAgent detection. For that, refer to this thread https://stackoverflow.com/a/13819253/8775880

So in the end, your code might look like this

const isDesktop(): boolean => {
   return navigator.orientation === undefined;
}

{
    path: 'path',
    loadChildren: () => {
      if(isDesktop())
        return import('./desktop.module').then((m) => m.DesktopModule);
      return import('./mobile.module').then((m) => m.MobileModule);
    }
}

Edit Keep in mind, however, that loadChildren will run only once when the path is loaded for the first time. So again, you might want to consider simply checking the screen dimensions. Let's say that 768px works for portrait on phone, but what if I open the site in landscape mode? In some situations, even landscape mode requires mobile UI. But if you only check client width, you will get desktop version.

Jiri Kralovec
  • 718
  • 5
  • 14