简体   繁体   English

Angular 4:用作全局变量的指令

[英]Angular 4: A directive to use as a global variable

I want to create a directive that I can use a template variable with so that I can get access to a global variable, similar to $rootScope in Angular.JS, without having to inject a service in every component that I need the variable in. 我想创建一个可以与模板变量一起使用的指令,以便可以访问全局变量(类似于Angular.JS中的$rootScope ),而不必在需要该变量的每个组件中注入服务。

For instance: 例如:

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

    constructor() {
        // Do some stuff to set 'this.ready'...
    }
}

I want to be able to use the above code in my template like so: 我希望能够在模板中使用上述代码,如下所示:

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

Is something like this possible? 这样的事情可能吗?

What about using a directive instead of ngIf, that way you only need inject your service into the directive, its also nice and DRY and minimial markup when using in your components. 如果使用指令而不是ngIf,那您只需要将服务注入到指令中,在组件中使用时,它也将具有不错的DRY和最小标记。

Something like 就像是

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

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

Then use 然后使用

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

And to toggle a class 并切换课程

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

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


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

  }
}

Then 然后

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

Plunkr here 普伦克在这里

I can only see 2 ways to do this but both involve injecting a common service in the components that need it. 我只能看到两种方法来实现此目的,但是两种方法都涉及在需要它的组件中注入一个公共服务。 You can do a little to ensure that you do not have to update the component code outside of the constructor and template. 您可以做一些事情以确保不必在构造函数和模板之外更新组件代码。

Option - Template calls service directly 选项-模板调用服务直接

application.component.ts 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){ }
}

Option - 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 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);
  }
}

You could pipe a random value to return a boolean depending on the global variable. 您可以通过pipe传递一个随机值以返回一个boolean具体取决于全局变量。

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

auth refers to an AuthPipe in this case which returns the global variable true or false 在这种情况下, auth指的是AuthPipe ,它返回全局变量truefalse

Now you only have to inject a dependency in the pipe? 现在您只需要在管道中注入依赖项?

It's a dirty fix but it should work since pipe s are accessible inside templates 这是一个肮脏的修复程序,但是应该可以使用,因为可以在模板内部访问pipe

Take a look at this approach: 看一下这种方法:

https://stackoverflow.com/a/39946948/222328 https://stackoverflow.com/a/39946948/222328

If you are okay with using your template inside your .ts file when you can do something like this (copying from that post): 如果可以执行以下操作(从该帖子复制),则可以在.ts文件中使用模板,可以:

Create a global class: 创建一个全局类:

export class Globals {
    isLoggedIn = true;
}

Then use this your component: 然后使用此组件:

import { Globals } from './globals';

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

The trick is the use of ` which makes this code execute {{globals.var}} 诀窍是使用`,使代码执行{{globals.var}}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM