【问题标题】:how to use a shared component with angular2?如何使用 angular2 的共享组件?
【发布时间】:2017-05-15 20:36:32
【问题描述】:

我的应用程序是这样构建的:

  1. 我主要的一些基本组件(主页、登录、关于...) app.module
  2. 应用程序每个部分的一些其他模块

我有一个组件,ToastComponent,我可能需要在任何地方使用它。 我适用于基本组件,但不适用于模块中包含的组件。

我阅读了很多关于如何共享服务的页面,但是(我不明白我在 angular2 中承认的所有内容),我仍然无法弄清楚如何使其适用于我的情况。 (我什至尝试了一个共享模块,但它更糟)

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

希望有人能指出正确的编码方式。 TIA

日本

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

Toast 组件:

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

这就是我添加“模式:[CUSTOM_ELEMENTS_SCHEMA]”的原因(我已经忘记了),但实际上它隐藏了我在运行时遇到的编译时错误!

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

【问题讨论】:

  • 您谈论您遇到的错误,但您的问题中没有包含任何错误。请添加确切的错误消息。
  • 完全没有错误:只有使用 setMessage 时没有出现在屏幕上的消息。
  • 您需要将 Toast 代码设置为服务。请参阅此处以获得更好的实施:github.com/johnpapa/event-view

标签: angular components


【解决方案1】:

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

因此,对您而言,您将在具有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;
}

最后,让我们来介绍一下这个观点。首先,我们在导航到也显示子组件的父组件时显示我们从共享服务获得的值。所以我们显示当前值并有按钮来操作值。

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

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

希望这会有所帮助! :) :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-18
    • 2017-07-17
    • 2017-10-25
    • 2018-01-30
    相关资源
    最近更新 更多