如何使用angular2的共享组件?

时间:2017-01-01 10:54:19

标签: angular components

我的应用程序以这种方式构建:

  1. 我主要的一些基本组件(home,login,about,...) app.module
  2. 应用程序每个部分的其他一些模块
  3. 我有一个组件ToastComponent,我可能需要在任何地方使用它。 我对基本组件工作正常,但不适用于模块中包含的组件。

    我阅读了许多关于如何共享服务的网页,但是(我不理解我在angular2中承认的所有内容),我仍然无法弄清楚如何让它在我的情况下工作。 (我甚至尝试过共享模块,但情况更糟)

    我遇到的问题是给予setMessage的消息(参见代码结尾)显示在控制台中,但不在屏幕上显示!?!

    希望有人可以指出我正确的编码方式。 TIA

    JP

    以下是我恢复到已知阶段后的代码(经过多次尝试)......

    ToastComponent:

    import { Component, Input } from '@angular/core';
    
    @Component({
      selector:    'app-toast',
      templateUrl: './toast.component.html',
      styleUrls:  ['./toast.component.css']
    })
    export class ToastComponent {
      @Input() message = { body: '', type: '' };
    
      setMessage(body, type, time = 5000) {
        this.message.body = body;
        this.message.type = type;
        console.log('ToastComponent %o' , this.message);
        setTimeout(() => { this.message.body = ''; }, time);
      }
    }
    

    app.module

    import { ToastComponent }           from './_shared/toast.component';
    ...
    import { LivresModule }             from './livres/livres.module'; // where toast will be used
    import { ExampleComponent }         from './example.component'; // where toast is working fine
    ...
    @NgModule({
      imports: [ ... , LivresModule  ],
      providers: [ ToastComponent, ... ],
      declarations: [ AppComponent, ToastComponent, ... ]
      exports: [ ToastComponent ],
      schemas: [ CUSTOM_ELEMENTS_SCHEMA ],
      bootstrap: [ AppComponent ],
    })  
    ...
    

    livres.module.ts

    ...
    import { ToastComponent }           from '../_shared/toast.component';
    import { AuteursComponent }         from './auteurs.component'; // where to use toast effectively
    ...
    @NgModule({ 
    ...
      providers: [ ToastComponent, ... ]
      declarations: [
    //     ToastComponent, // error as declared twice with app.module : OK so commented
    ...
    

    auteurs.component

    ...
    import { ToastComponent }     from '../_shared/toast.component';
    ...
    constructor(private http: Http, private authorService: AuthorService,
                  private toast: ToastComponent ) { }
    ...
    addAuthor() {
    ...
      this.toast.setMessage('Auteur ajouté', 'success');
    }
    

    auteurs.component.html

    ...<app-toast [message]="toast.message"></app-toast>...
    

    auteurs.component。*是app.module的组件部分的副本,可以正常工作。

    新信息: 我正在重新创建一个模仿我正在构建的应用程序的轻量级应用程序,并且我在模块中的页面出现此错误:

        Unhandled Promise rejection: Template parse errors:
        Can't bind to 'message' since it isn't a known property of 'app-toast'.
        1. If 'app-toast' is an Angular component and it has 'message' input, then verify that it is part of this module.
        2. If 'app-toast' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message.
         ("<app-toast [ERROR ->][message]="toast.message"></app-toast>
    <p> page2 works!  </p>
    <button (click)="displayMsg()"> Click !"): Page2Component@0:11
    

    这就是为什么我添加了“schemas:[CUSTOM_ELEMENTS_SCHEMA]”(我已经忘记了这一点),但事实上它在编译时隐藏了我在运行时的错误!

    转换为服务不会带来html代码和css。

1 个答案:

答案 0 :(得分:0)

如上面的评论所述,共享服务可能就是您所需要的。下面是一个简单的共享服务实现,我希望这可以帮助您理解共享服务,因为您提到您无法理解它:)

因此,对于您,您将使用setMessage方法实现此共享服务,然后在auteurs.component中,您将在构造函数中注入该服务,然后您将在当您想要更改消息的值时进行服务,如下所示:

this.sharedService.sharedMessage = // your new message here

只需在您需要的所有组件中检索该消息,例如:

this.message = this.sharedService.sharedMessage;

这就是你如何访问它。但请看下面的例子!

这里我实现了一个父组件和子组件,只是为了说明它们如何受到两个组件中所做更改的影响。我已经采取了一些参考你的代码,作为你想要在你的应用程序中操作的“类型”和“身体”。您可以像我在此示例中那样实现它,它总是在服务中被操纵,因此使用此服务的所有组件将具有与服务中存在的值相同的值!我还会添加一些一步一步的图片:)你可以将ToastComponent作为一种服务,从你想要的地方访问它:)

首先,一个界面:

export interface IShared {
    body: string;
    type: string;
}

在服务中,我们设置了两个组件将共享的sharedMessage。我们还有为sharedMessage

设置新内容的方法
@Injectable()
export class SharedService {

    sharedMessage;

    sharedMessage: IShared = {
        body: 'old body',
        type: 'old type',
    };

    setMessage(body, type) {
        this.sharedMessage.body = body;
        this.sharedMessage.type = type;
    }

    constructor() { }
}

在我提出的这种情况下,您的父母和儿童成分实际上是相同的。我们在构造函数中都有(是的,而是在OnInit中执行),以便我们从服务中获取消息的当前值。在这里,我们还有操纵该值的方法。将在共享服务中调用该方法来执行值操作的方法。一旦你了解它,这实际上并不那么困难。以下是父和子的组件和html视图。

您的父组件:

HTML:

<h2>Hey, let's play with shared service!</h2>
<button (click)="setMessage('new Body', 'new Type')">Set new (parent)</button>
<h4>This message is in parent component: <b>{{message.body}}, {{message.type}}</b></h4>
<br>
<child-component></child-component>

组件:

message;

setMessage(body, type) {
    this.message.body = body;
    this.message.type = type;
    this.sharedService.sharedMessage = this.message;
}

constructor(private sharedService: SharedService) {
        this.message = this.sharedService.sharedMessage;
}

您的孩子组成部分:

HTML:

<button (click)="setMessage('newest Body', 'newest Type')">Set newest (child)</button>
<h4>This message is in child component: <b>{{message.body}}, {{message.type}></b></h4>

组件:

message;

setMessage(body, type) {
    this.message.body = body;
    this.message.type = type;
    this.sharedService.sharedMessage = this.message;
}

constructor(private sharedService: SharedService) {
    this.message = this.sharedService.sharedMessage;
}

最后,让我们来看看这个观点。首先,我们展示了在导航到同时显示子组件的父级时从共享服务获得的值。因此,我们显示当前值并具有操作值的按钮。

enter image description here

然后,当我们单击父组件的按钮时,我们将获得为父组件和子组件设置的新值,因为它们共享相同的服务。

enter image description here

最后我们点击了子组件的按钮:)

enter image description here

希望这有帮助! :):)