无法在 angular 7 中执行另一个组件的方法
Cannot execute method of a component from another in angular 7
我正在尝试通过方法 callToggleSidebarOnToggleSidebarBtn() 从 HeaderComponent 调用 SidebarComponent 的方法 toggleSidebar() ,但我收到一些我不明白的错误。如何使用另一个组件的方法?
我在HeaderComponent中引入了SidebarComponent;
在 HeaderComponent 中,我在构造函数中添加了 SidebarComponent 以使用她的方法之一。我试图删除 header.component.ts 的方法 callToggleSidebarOnToggleSidebarBtn() 但我得到相同的输出。
sidebar.component.html :
<div id="sidebar" class="bg-gray">
<a href="" class="nav-link"><i class="fa fa-calendar"></i> Event</a>
<a href="" class="nav-link"><i class="fa fa-user-circle-o"></i> Profile</a>
<a href="" class="nav-link"><i class="fa fa-commenting-o"></i> Chat</a>
<a href="" class="nav-link"><i class="fa fa-gear"></i> Setting</a>
<a href="" class="nav-link"><i class="fa fa-question-circle-o"></i> Help</a>
<a href="" class="nav-link"><i class="fa fa-sign-out"></i> Log out</a>
sidebar.component.ts :
import { Component, OnInit } from '@angular/core';
import * as $ from 'jquery';
@Component({
selector: 'app-sidebar',
templateUrl: './sidebar.component.html',
styleUrls: ['./sidebar.component.css']
})
export class SidebarComponent implements OnInit {
constructor() { }
ngOnInit() {
}
// Display the sidebar if it's not visible and otherwise if else.
toggleSidebar() {
$("#sidebar").animate({width: 'toggle'});
}
}
header.component.html :
<div>
<nav class="navbar navbar-expand-lg d-flex justify-content-between fixed-top">
<button class="btn" (click)="callToggleSidebarOnToggleSidebarBtn()"><i class="fa fa-reorder"></i></button>
<div class="d-flex p-0 m-0">
<a href="#" class="nav-link d-none d-lg-block">Event</a>
<a href="#" class="nav-link d-none d-lg-block">Contact Us</a>
<a href="#" class="nav-link d-none d-lg-block">About Us</a>
<a href="#" class="nav-link d-none d-lg-block"><i class="fa fa-user-circle"></i></a>
</div>
<div class="d-flex">
<a href="#" class="nav-link"><i class="fa fa-bell"></i></a>
<a href="#" class="nav-link"><i class="fa fa-globe"></i></a>
</div>
</nav>
<div class="d-sm-flex align-items-center justify-content-between" id="secondMenu">
<div id="logoContainer">
<img src="../assets/images/logo.png" alt="" id="logo">
</div>
<div class="input-group">
<div class="input-group-prepend">
<button class="input-group-text btn dropdown-toggle" data-toggle="dropdown">Meeting</button>
<div class="dropdown-menu">
<a class="dropdown-item" class="dropdown-item">Action</a>
<a class="dropdown-item" class="dropdown-item">Another action</a>
<a class="dropdown-item" class="dropdown-item">Something else here</a>
</div>
</div>
<input type="text" class="form-control" placeholder="What are you looking for ?" aria-label="Search">
<div class="input-group-append">
<button class="btn" type="submit"><i class="fa fa-search"></i></button>
</div>
</div>
</div>
<div>
header.component.ts :
import { Component, OnInit } from '@angular/core';
import { SidebarComponent } from '../sidebar/sidebar.component';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
constructor(private sidebarComponent : SidebarComponent) { }
ngOnInit() {
}
callToggleSidebarOnToggleSidebarBtn() {
this.sidebarComponent.toggleSidebar();
}
}
我希望能够通过单击 header 左上角的按钮来切换 sidebar.component.html 的内容,但实际输出是:
ERROR Error: Uncaught (in promise): Error: StaticInjectorError(AppModule)
[HeaderComponent -> SidebarComponent]:
StaticInjectorError(Platform: core)[HeaderComponent -> SidebarComponent]:
NullInjectorError: No provider for SidebarComponent!
Error: StaticInjectorError(AppModule)[HeaderComponent -> SidebarComponent]:
StaticInjectorError(Platform: core)[HeaderComponent -> SidebarComponent]:
NullInjectorError: No provider for SidebarComponent!
at NullInjector.push../node_modules/@angular/core/fesm5/core.js.NullInjector.get (core.js:3228)
at resolveToken (core.js:3473)
at tryResolveToken (core.js:3417)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:3314)
at resolveToken (core.js:3473)
at tryResolveToken (core.js:3417)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:3314)
at resolveNgModuleDep (core.js:19784)
at NgModuleRef_.push../node_modules/@angular/core/fesm5/core.js.NgModuleRef_.get (core.js:20473)
at resolveDep (core.js:20844)
at resolvePromise (zone.js:831)
at resolvePromise (zone.js:788)
at zone.js:892
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
at Object.onInvokeTask (core.js:16147)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)
at drainMicroTaskQueue (zone.js:601)
组件不是依赖项,它们不能被注入。
要执行您想要的操作,请在页眉中找到侧边栏并为其提供参考:
<app-sidebar #sidebarReference></app-sidebar>
您现在可以在模板中使用它:
<button (click)="sidebarReference.toggleSidebar()">...</button>
或在您的组件中:
@ViewChild(SidebarComponent) sidebar: SidebarComponent;
// or, if several sidebars are in the template,
@ViewChild('sidebarReference') sidebar: SidebarComponent;
this.sidebar.toggleSidebar();
据我所知,您不能将组件注入另一个组件。如果您想要组件间通信,您可以:
1.使用服务
2. 或者根据组件之间的关系使用@Input或@Output构造。
不要在 Header 组件中创建边栏组件的实例,而是使用以下命令创建服务即 appService.ts
,
ng generate service app
在该服务中写入以下代码
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AppService {
flagChange:Subject<boolean> = new Subject<boolean>();
constructor() { }
setFlag(flagValue){
this.flagChange.next(flagValue);
}
}
然后在我们的 header.component.ts
中将该服务实例注入为
import { Component, OnInit } from '@angular/core';
import { AppService } from './app.service';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
flag:boolean = false;
constructor(private appService : AppService) { }
ngOnInit() {
}
callToggleSidebarOnToggleSidebarBtn() {
this.appService.setFlag(!this.flag);
}
}
然后在我们的sidebar.component.ts
中,更新代码如下,
import { Component, OnInit } from '@angular/core';
import * as $ from 'jquery';
import { AppService } from './app.service';
@Component({
selector: 'app-sidebar',
templateUrl: './sidebar.component.html',
styleUrls: ['./sidebar.component.css']
})
export class SidebarComponent implements OnInit {
constructor(private appService: AppService) { }
ngOnInit() {
this.appService.flagChange.subscribe((flag) => {
$("#sidebar").animate({width: 'toggle'});
})
}
}
因此,当用户单击图标时,header 组件中的标志值被切换,此更改是 registered/given 到 AppService 中使用 next() 函数的 flagChange 变量,并且使用订阅观察此更改侧边栏组件中的方法。
为了解决这个问题,我先去掉了header.component.ts中侧边栏的导入和构造函数。这是我的最终 header.component.ts :
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
您可以看到我所做的所有更改。
然后我在 header 中添加以下代码来引用 SidebarComponent :
<app-sidebar #sidebarReference></app-sidebar>
您现在可以在 header.component.ts
的模板中使用它
<button class="btn" (click)="sidebarReference.toggleSidebar()"><i class="fa fa-reorder"></i></button>
我正在尝试通过方法 callToggleSidebarOnToggleSidebarBtn() 从 HeaderComponent 调用 SidebarComponent 的方法 toggleSidebar() ,但我收到一些我不明白的错误。如何使用另一个组件的方法?
我在HeaderComponent中引入了SidebarComponent; 在 HeaderComponent 中,我在构造函数中添加了 SidebarComponent 以使用她的方法之一。我试图删除 header.component.ts 的方法 callToggleSidebarOnToggleSidebarBtn() 但我得到相同的输出。
sidebar.component.html :
<div id="sidebar" class="bg-gray">
<a href="" class="nav-link"><i class="fa fa-calendar"></i> Event</a>
<a href="" class="nav-link"><i class="fa fa-user-circle-o"></i> Profile</a>
<a href="" class="nav-link"><i class="fa fa-commenting-o"></i> Chat</a>
<a href="" class="nav-link"><i class="fa fa-gear"></i> Setting</a>
<a href="" class="nav-link"><i class="fa fa-question-circle-o"></i> Help</a>
<a href="" class="nav-link"><i class="fa fa-sign-out"></i> Log out</a>
sidebar.component.ts :
import { Component, OnInit } from '@angular/core';
import * as $ from 'jquery';
@Component({
selector: 'app-sidebar',
templateUrl: './sidebar.component.html',
styleUrls: ['./sidebar.component.css']
})
export class SidebarComponent implements OnInit {
constructor() { }
ngOnInit() {
}
// Display the sidebar if it's not visible and otherwise if else.
toggleSidebar() {
$("#sidebar").animate({width: 'toggle'});
}
}
header.component.html :
<div>
<nav class="navbar navbar-expand-lg d-flex justify-content-between fixed-top">
<button class="btn" (click)="callToggleSidebarOnToggleSidebarBtn()"><i class="fa fa-reorder"></i></button>
<div class="d-flex p-0 m-0">
<a href="#" class="nav-link d-none d-lg-block">Event</a>
<a href="#" class="nav-link d-none d-lg-block">Contact Us</a>
<a href="#" class="nav-link d-none d-lg-block">About Us</a>
<a href="#" class="nav-link d-none d-lg-block"><i class="fa fa-user-circle"></i></a>
</div>
<div class="d-flex">
<a href="#" class="nav-link"><i class="fa fa-bell"></i></a>
<a href="#" class="nav-link"><i class="fa fa-globe"></i></a>
</div>
</nav>
<div class="d-sm-flex align-items-center justify-content-between" id="secondMenu">
<div id="logoContainer">
<img src="../assets/images/logo.png" alt="" id="logo">
</div>
<div class="input-group">
<div class="input-group-prepend">
<button class="input-group-text btn dropdown-toggle" data-toggle="dropdown">Meeting</button>
<div class="dropdown-menu">
<a class="dropdown-item" class="dropdown-item">Action</a>
<a class="dropdown-item" class="dropdown-item">Another action</a>
<a class="dropdown-item" class="dropdown-item">Something else here</a>
</div>
</div>
<input type="text" class="form-control" placeholder="What are you looking for ?" aria-label="Search">
<div class="input-group-append">
<button class="btn" type="submit"><i class="fa fa-search"></i></button>
</div>
</div>
</div>
<div>
header.component.ts :
import { Component, OnInit } from '@angular/core';
import { SidebarComponent } from '../sidebar/sidebar.component';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
constructor(private sidebarComponent : SidebarComponent) { }
ngOnInit() {
}
callToggleSidebarOnToggleSidebarBtn() {
this.sidebarComponent.toggleSidebar();
}
}
我希望能够通过单击 header 左上角的按钮来切换 sidebar.component.html 的内容,但实际输出是:
ERROR Error: Uncaught (in promise): Error: StaticInjectorError(AppModule)
[HeaderComponent -> SidebarComponent]:
StaticInjectorError(Platform: core)[HeaderComponent -> SidebarComponent]:
NullInjectorError: No provider for SidebarComponent!
Error: StaticInjectorError(AppModule)[HeaderComponent -> SidebarComponent]:
StaticInjectorError(Platform: core)[HeaderComponent -> SidebarComponent]:
NullInjectorError: No provider for SidebarComponent!
at NullInjector.push../node_modules/@angular/core/fesm5/core.js.NullInjector.get (core.js:3228)
at resolveToken (core.js:3473)
at tryResolveToken (core.js:3417)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:3314)
at resolveToken (core.js:3473)
at tryResolveToken (core.js:3417)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:3314)
at resolveNgModuleDep (core.js:19784)
at NgModuleRef_.push../node_modules/@angular/core/fesm5/core.js.NgModuleRef_.get (core.js:20473)
at resolveDep (core.js:20844)
at resolvePromise (zone.js:831)
at resolvePromise (zone.js:788)
at zone.js:892
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
at Object.onInvokeTask (core.js:16147)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)
at drainMicroTaskQueue (zone.js:601)
组件不是依赖项,它们不能被注入。
要执行您想要的操作,请在页眉中找到侧边栏并为其提供参考:
<app-sidebar #sidebarReference></app-sidebar>
您现在可以在模板中使用它:
<button (click)="sidebarReference.toggleSidebar()">...</button>
或在您的组件中:
@ViewChild(SidebarComponent) sidebar: SidebarComponent;
// or, if several sidebars are in the template,
@ViewChild('sidebarReference') sidebar: SidebarComponent;
this.sidebar.toggleSidebar();
据我所知,您不能将组件注入另一个组件。如果您想要组件间通信,您可以: 1.使用服务 2. 或者根据组件之间的关系使用@Input或@Output构造。
不要在 Header 组件中创建边栏组件的实例,而是使用以下命令创建服务即 appService.ts
,
ng generate service app
在该服务中写入以下代码
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AppService {
flagChange:Subject<boolean> = new Subject<boolean>();
constructor() { }
setFlag(flagValue){
this.flagChange.next(flagValue);
}
}
然后在我们的 header.component.ts
中将该服务实例注入为
import { Component, OnInit } from '@angular/core';
import { AppService } from './app.service';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
flag:boolean = false;
constructor(private appService : AppService) { }
ngOnInit() {
}
callToggleSidebarOnToggleSidebarBtn() {
this.appService.setFlag(!this.flag);
}
}
然后在我们的sidebar.component.ts
中,更新代码如下,
import { Component, OnInit } from '@angular/core';
import * as $ from 'jquery';
import { AppService } from './app.service';
@Component({
selector: 'app-sidebar',
templateUrl: './sidebar.component.html',
styleUrls: ['./sidebar.component.css']
})
export class SidebarComponent implements OnInit {
constructor(private appService: AppService) { }
ngOnInit() {
this.appService.flagChange.subscribe((flag) => {
$("#sidebar").animate({width: 'toggle'});
})
}
}
因此,当用户单击图标时,header 组件中的标志值被切换,此更改是 registered/given 到 AppService 中使用 next() 函数的 flagChange 变量,并且使用订阅观察此更改侧边栏组件中的方法。
为了解决这个问题,我先去掉了header.component.ts中侧边栏的导入和构造函数。这是我的最终 header.component.ts :
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
您可以看到我所做的所有更改。
然后我在 header 中添加以下代码来引用 SidebarComponent :
<app-sidebar #sidebarReference></app-sidebar>
您现在可以在 header.component.ts
的模板中使用它<button class="btn" (click)="sidebarReference.toggleSidebar()"><i class="fa fa-reorder"></i></button>