Angular 4: Leveraging a directive as a universal constant

I am looking to develop a directive that allows me to utilize a template variable in order to access a global variable, much like $rootScope in Angular.JS. The goal is to avoid having to inject a service into every component where I need access to the variable.

Here's an example:

@Directive({
    selector: '[app]',
    exportAs: 'app'
})
export class AppDirective {
    isLoggedIn: boolean = false;

    constructor() {
        // Code to initialize 'this.ready' will go here...
    }
}

The intention is to use the code above in my template as follows:

<div #app>
    <div *ngIf="app.isLoggedIn">...</div>
</div>

Is it possible to achieve something like this?

Answer №1

Instead of using ngIf, consider implementing a directive for more efficient code. By injecting your service into the directive, you can maintain DRY (Don't Repeat Yourself) principles and keep markup minimal in your components.

You can create a directive like this:

@Directive({
  selector: '[showIfLoggedIn]'
})
export class ShowIfLoggedInDirective implements OnInit {
  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainerRef: ViewContainerRef
  ) { }

  ngOnInit() {
    var isLoggedIn = false; // Use service here and inject into the constructor.
    if(isLoggedIn) {
        this.viewContainerRef.createEmbeddedView(this.templateRef);
      } else {
        this.viewContainerRef.clear();
      }
  }
}

To use it:

<h2 *showIfLoggedIn> I am logged in </h2>

To apply a class dynamically:

@Directive({
  selector : '[applyClassIfLoggedIn]'
})

export class ApplyClassIfLoggedIn implements OnInit {
  @Input('applyClassIfLoggedIn') className;
  constructor(
    private ele: ElementRef,
    private renderer: Renderer2
  ) { }


  ngOnInit() {
    var isLoggedIn = true; // Use service here.
    if(isLoggedIn) {
        this.renderer.addClass(this.ele.nativeElement, this.className);
    }

  }
}

Then:

<h2 applyClassIfLoggedIn='logged-in'>Red if logged in </h2>

Check out the Plunkr example here

Answer №2

There are two main approaches to achieve this task, both requiring the injection of a common service into the components that need it. By implementing these methods, you can minimize the need to modify the component code beyond the constructor and template sections.

Method 1: Direct Service Call from Template

application.component.ts

import {SecurityService} from './security.service';
@Component({
    selector: '[App]',
    template: `<div *ngIf="securityService.isLoggedIn">Logged in!</div>`
})
export class ApplicationComponent {
  constructor(public securityService: SecurityService){ }
}

Method 2: Using a Shared Abstract Class

security-context.component.ts

import {SecurityService} from './security.service';
export abstract class SecurityContextComponent {
  constructor(protected securityService: SecurityService){}

  get isLoggedIn(): boolean{
    return this.securityService.isLoggedIn;
  }
}

application.component.ts

import {SecurityContextComponent} from './security-context.component';
import {SecurityService} from './security.service';

@Component({
    selector: '[App]',
    template: `<div *ngIf="isLoggedIn">Logged in!</div>`
})
export class ApplicationComponent implements SecurityContextComponent {
  constructor(securityService: SecurityService){
    super(securityService);
  }
}

Answer №3

To determine if a random value returns a boolean based on the global variable, you can use the pipe method.

<div #app>
    <div *ngIf="'randomstring' | auth">...</div>
</div>

In this scenario, auth is associated with an AuthPipe that outputs either true or false depending on the global variable.

Simply injecting a dependency into the pipe should suffice for this purpose.

While it may not be the most elegant solution, using pipes within templates is effective in achieving the desired outcome.

Answer №4

Here is an interesting approach to consider:

If you are open to utilizing your template within your .ts file, you can implement something similar to the following (taken from the provided post):

Start by creating a global class:

export class Globals {
    isLoggedIn = true;
}

Then incorporate this into your component:

import { Globals } from './globals';

@Component({
    selector: 'my-app',
    template: `<h1>My Component {{globals.isLoggedIn}}<h1/>`
})
export class AppComponent {
    constructor(){
    }
}

The key lies in using backticks (`) which enables the execution of {{globals.var}}

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

Using Angular 2 to inject JSON data through HTTP requests

http://localhost:3000/userinfo [ { "username": "simon", "password": "password1" }, { "username": "bala", "password": "password2" }, { "username": "prabha", "password": "password3" } ] myservice.service.ts import { Inje ...

When utilizing Monggose, Angular, and Node, a route containing the deleteOne method repeatedly reports that the object has been successfully deleted, despite the delete count remaining

I've encountered a similar issue to others, but their solutions didn't work for me. I'm working on a small MEAN app with mongoose and facing a problem when trying to delete a user or any other object stored in the collection. The route seems ...

Dynamically passing output placeholders through ng-content in an Angular component template

Can a component handle dynamic projection in this way? <my-component [date]="2022-03-22"> <p>This particular date falls on a <strong #dayName></strong>! It is in week number <span #weekNum></span> of year &l ...

Unable to locate the module '@vitejs/plugin-react' or its associated type

After creating the project with npm create vite@latest and selecting ts-react, everything seemed to work fine when I ran npm run dev. However, in my vs code editor, I encountered the error message "Cannot find module '@vitejs/plugin-react' or its ...

What's causing the subscription feature to malfunction in a fresh browser tab?

I am facing an issue with camera entries on an angular website. Whenever I click on an entry, a new window opens to display the camera livestream. However, I am having trouble with the subscribe functionality. Important note: Once the window is open, subs ...

Pause for Progress - Angular 6

I'm looking for a solution to solve the following issue. I need to access a property that will store data from an http request. Therefore, I want to verify this property only after the transaction is completed. validateAuthorization(path: string): ...

Automatically increase the version with Yarn auto Version Bump

My package.json file uses a 4-digit version format like "version": "1.3.0-0". When I run the command yarn version --prerelease on my Windows system, it correctly shows: info Current version: 1.3.0-0 info New version: 1.3.0-1 However, ...

The Angular application is not able to initiate the POST request

I have developed a database to store game data. Through testing, I have found that adding a "team" to a "game" functions correctly. However, my Angular application is not successfully triggering the database. I have verified that the database operation wo ...

ts1109: An error occurred as there was an expectation for an angular

I am encountering an error while creating a simple form with Angular using a reactive form. I'm puzzled as to why it's indicating that something is missing: Although I have created forms numerous times before, this is the first instance of such ...

Issue with dispatching actions in React using TypeScript and hooks

Can you please point out what I'm doing wrong here: I am encountering the following error Type '{ wishList: any; addBookToWishList: (book: any) => void; }' is not assignable to type '{ wishList: never[]; }'. Object literal may onl ...

What are the steps to enable screen sharing within an Electron application?

I am currently working on developing two applications for screen sharing within a LAN setting using Electron, React, and TypeScript. The first app will capture the screen stream and broadcast it via UDP, while the second app, running on multiple devices, w ...

Send a variable from a next.js middleware to an API request

I've been attempting to pass a middleware variable to my API pages via "req" but have encountered some issues Even after trying to send the user token to pages using "req", it consistently returns null The middleware file in question is: pages/api/u ...

Loading components dynamically in Angular2 with parameters

I'm currently working on developing a table component that can generate a table based on a column description and raw data. While I've managed to implement the basic functionality smoothly, I also want to have the ability to customize the render ...

Installing failed due to an error in the postinstall script of @angular/core version 9

I'm at the beginning of my coding journey and I am looking to set up a source code on my computer. node -v v12.16.1 npm -v 6.13.4 Could you assist me in resolving this issue that arises when I try to run the npm install command (on Windows 7 ...

Alert an Angular 2 component about changes triggered by a service

Currently working with Angular 2 and utilizing an AuthService for authentication. I am at a crossroads on how to effectively inform other components when a user logs in or out. Seeking advice on the best approach for managing this situation. Any insights ...

For an unknown reason, I am facing difficulties in using the Storage feature from @angular/fire in ANGULAR 16

Recently I started exploring Angular/Fire and decided to test out some of its features by creating a basic app. Firestore and authentication were working smoothly, but when I attempted to include Storage, an error message popped up: ERROR FirebaseError: ...

Killing the command prompt in Typescript: A step-by-step guide

Is there a way to completely close the cmd where the typescript file is running but unable to do so? How can this be achieved? console.log('This ts file must be terminate itself'); let asdef = process.pid; let asdeff = process.ppid; const {exe ...

What is the best way to establish communication between the browser and an express.js server while utilizing angular ssr?

I've encountered a server-side rendering (SSR) issue that does not seem to be addressed in either the Angular documentation or the new Angular developer documentation. My inquiry pertains to transferring data from the browser to the server, as oppose ...

What is the process for developing an interface adapter using TypeScript?

I need to update the client JSON with my own JSON data Client JSON: interface Cols { displayName: string; } { cols:[ { displayName: 'abc'; } ] } My JSON: interface Cols { label: string; } { cols:[ { label:&a ...

The upcoming router is not compatible with the NextPage type

I am currently working on introducing dynamic routing into an application that was originally designed with static routes. However, I am facing some confusion as I encounter TypeScript errors that are difficult for me to understand. Below is the code snipp ...