我的目标是在子组件中使用依赖注入来访问父组件中的属性。我想让它像this一样工作。 正如您可以在控制台中看到“第二个孩子”,模板来自第二个孩子并显示在父级中。它不需要第二个子组件选择器位于父模板中。
我的实际应用程序(下面的代码)的目标是,通过单击CHILD中的“更改有效状态”按钮,我将能够在PARENT中切换true和false ...尽管只通过a引用了孩子路由器插座。
我选择了这个解决方案,因为我没有必要使用父级中的组件选择器来访问子数据....但是我收到了错误:
ERROR Error: Uncaught (in promise): Error: StaticInjectorError(AppModule)[NewUserComponent -> NewUserInputComponent]:
StaticInjectorError(Platform: core)[NewUserComponent -> NewUserInputComponent]:
NullInjectorError: No provider for NewUserInputComponent!
Error: StaticInjectorError(AppModule)[NewUserComponent -> NewUserInputComponent]:
StaticInjectorError(Platform: core)[NewUserComponent -> NewUserInputComponent]:
NullInjectorError: No provider for NewUserInputComponent!
at NullInjector.push../node_modules/@angular/core/fesm5/core.js.NullInjector.get (core.js:979)
...当我将此解决方案应用到我的实际应用程序中时(当我取消注释下面的PARENT COMPONENT中的代码时)。
感谢您提供任何帮助。
以下是我实际应用的代码: PARENT COMPONENT(我已经注释掉了修复我的数据共享问题但导致错误的代码):
import { UserManagementModule } from './../user-management.module';
import { Component, OnInit } from '@angular/core';
import { routerTransition, slideToRight, slideToLeft } from '../../../router.animations';
import { Router, NavigationEnd } from '@angular/router';
// import { NewUserInputComponent } from './new-user-input/new-user-input.component'; //bringing accessability/form validation state from child
@Component({
selector: 'app-new-user',
templateUrl: './new-user.component.html',
styleUrls: ['./new-user.component.css'],
host: {
'class': 'blade-container'
},
animations: [slideToRight()]
})
export class NewUserComponent implements OnInit {
isRestored = true;
minimizeVar = false;
test = false;
newUserInfoValidState = false;
// constructor(private router: Router, public newuserinput: NewUserInputComponent) {
constructor(private router: Router) {
// this.newUserInfoValidState = newuserinput.newUserInfoValidState;
this.test = false;
}
ngOnInit() {
console.log(this.newUserInfoValidState);
}
getVState(componentRef) {
this.test = componentRef.test;
}
private scrollToSectionHook() {
this.router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
const tree = this.router.parseUrl(this.router.url);
if (tree.fragment) {
const element = document.querySelector('#' + tree.fragment);
if (element) {
setTimeout(() => {
element.scrollIntoView({ behavior: 'smooth', block: 'end', inline: 'nearest' });
}, 500);
}
}
}
});
}
}
儿童成分:
相关:
public newUserInfoValidState = true;
changeTest() {
this.newUserInfoValidState = !this.newUserInfoValidState;
console.log(this.newUserInfoValidState);
}
_
import { EventEmitter } from '@angular/core';
import { Component, OnInit, Output } from '@angular/core';
import { slideToRight } from '../../../../router.animations';
import { Router, ActivatedRoute, UrlSegment, NavigationEnd } from '@angular/router';
@Component({
selector: 'app-new-user-input',
templateUrl: './new-user-input.component.html',
styleUrls: ['./new-user-input.component.css'],
animations: [slideToRight()]
})
export class NewUserInputComponent implements OnInit {
test = true;
public newUserInfoValidState = true;
// newUserInfoComplete = false;
// @Output() newUserInfoCompleteEvent = new EventEmitter<boolean>();
constructor(private router: Router, r: ActivatedRoute) {
r.url.subscribe((s: UrlSegment[]) => {
console.log("url", s); //https://vsavkin.com/angular-router-understanding-router-state-7b5b95a12eab
});
}
ngOnInit() {
}
changeTest() {
this.newUserInfoValidState = !this.newUserInfoValidState;
console.log(this.newUserInfoValidState);
}
// sendNewUserInfoComplete() {
// this.newUserInfoCompleteEvent.emit(this.newUserInfoComplete);
// }
displaySibling() {
console.log(this.router);
this.router.navigate(['../', { outlets: { newuserorginfo: ['newuserorginfo'] } }])
}
closeBlade() {
this.router.navigate([{ outlets: { newuserinput: null } }]);
}
private scrollToSectionHook() {
this.router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
const tree = this.router.parseUrl(this.router.url);
if (tree.fragment) {
const element = document.querySelector('#' + tree.fragment);
if (element) {
setTimeout(() => {
element.scrollIntoView({ behavior: 'smooth', block: 'end', inline: 'nearest' });
}, 500);
}
}
}
});
}
}
父母模板:
相关:
<br> injected: {{newUserInfoValidState}}
_
<!-- <app-page-header [icon]="'fa fa-users'"></app-page-header> -->
<!-- <app-page-header [heading]="'New User Request'"></app-page-header> -->
<!--BLADE LAYER 2-->
<div class="blade" [@routerTransition] [ngClass]="{'is-minimized-blade':minimizeVar, 'is-restored-blade':isRestored}">
<div class="blade-header" [ngClass]="{'is-minimized-header':minimizeVar}">
<h3 [ngClass]="{'is-minimized-headerText':minimizeVar}">New User Request</h3>
<!-- BLADE Window Operations -->
<div class="window-functions">
<!-- Minimize -->
<div class="inline" *ngIf="minimizeVar; else minimizeElseBlock">
<a (click)='minimizeVar=!minimizeVar'>
<i class="fa fa-plus-circle"></i>
</a>
</div>
<ng-template #minimizeElseBlock>
<a (click)='minimizeVar=!minimizeVar'>
<i class="fa fa-window-minimize"></i>
</a>
</ng-template>
<!-- Maximize -->
<div class="inline" *ngIf="isRestored; else elseBlock">
<a (click)='isRestored=!isRestored'>
<i class="fa fa-window-restore"></i>
</a>
</div>
<ng-template #elseBlock>
<a (click)='isRestored=!isRestored'>
<i class="fa fa-window-maximize"></i>
</a>
</ng-template>
<!-- Close -->
<a routerLink='/layout/usermanagement' routerLinkActive='router-link-active'>
<i class="fa fa-window-close"></i>
</a>
</div>
</div>
<!-- BLADE Contents -->
<ul>
<li>
<li [routerLink]="['./', { outlets: { newuserinput: ['newuserinput'] } } ]" routerLinkActive='active'>
<h4 class="font-weight-light">1 User Information
<i class="fa fa-chevron-right"></i>
<br>test: {{test}}
<br> injected: {{newUserInfoValidState}}
</h4>
</li>
<br>
<li>
<!-- <li *ngIf='newUserInfoValidState'>
<h4 class="font-weight-light">2 Organization
<i class="fa fa-chevron-right"></i>
</h4>
</li> -->
<li [routerLink]="[{ outlets: { newuserorginfo: ['newuserorginfo'] } } ]" routerLinkActive='active'>
<h4 class="font-weight-light">2 Organization
<i class="fa fa-chevron-right"></i>
</h4>
</li>
<br>
<li>
<li [routerLink]="[{ outlets: { newusersupervisorinfo: ['newusersupervisorinfo'] } } ]" routerLinkActive='active'>
<h4 class="font-weight-light">3 Supervisor
<i class="fa fa-chevron-right"></i>
</h4>
</li>
<br>
<li>
<li [routerLink]="[{ outlets: { newusersecurityinfo: ['newusersecurityinfo'] } } ]" routerLinkActive='active'>
<h4 class="font-weight-light">4 Security Profiles
<i class="fa fa-chevron-right"></i>
</h4>
</li>
</ul>
</div>
<!-- To BLADE LAYER 3 -->
<router-outlet></router-outlet>
<!-- <router-outlet name="newuserinput" (newUserInfoCompleteEvent)="receiveNewUserInfoComplete($event)"></router-outlet> -->
<router-outlet (activate)='getVState($event)' name="newuserinput"></router-outlet>
<router-outlet name="newuserorginfo"></router-outlet>
<router-outlet name="newusersupervisorinfo"></router-outlet>
<router-outlet name="newusersecurityinfo"></router-outlet>
<!-- end -->
<!-- For ViewChild: bringing form validity state from child -->
<!-- <app-new-user-input style="display:none;"></app-new-user-input> -->
<!-- can't do this because putting the child component selector in the parent disables the childs router outlet -->
儿童模板:
相关:
<button (click)="changeTest()">Change Valid State</button>
_
<div class="blade" [@routerTransition]>
<div class="blade-header">
<h3>User Information</h3>
<div class="window-functions">
<i class="fa fa-window-minimize"></i>
<i class="fa fa-window-restore"></i>
<i class="fa fa-window-maximize"></i>
<a [routerLink]="['../',{ outlets: { newuserorginfo: ['newuserorginfo'] } } ]" routerLinkActive='router-link-active'>
<!-- <a routerLink='/layout/usermanagement/(newuser:newuser)' routerLinkActive='router-link-active'> -->
<i class="fa fa-window-close"></i>
<!-- <i (click)='closeBlade()' class="fa fa-window-close"></i> -->
</a>
</div>
</div>
<form action="submit">
<!-- <label for="firstname">First Name:</label> -->
User type:
<br>
<select required>
<option value="" hidden disabled selected data-default></option>
<option value="Customer">Customer</option>
<option value="Organization Administrator">Organization Administrator</option>
<option value="Customer Service Representative">Customer Service Representative</option>
<option value="Customer Service Administrator">Customer Service Administrator</option>
</select>
<br>
<br> First name:
<br>
<input required type="text" name="firstname" value="Richard">
<br>
<br> Last name:
<br>
<input required type="text" name="lastname" value="Dawkins">
<br>
<br> Cell phone:
<br>
<input required type="tel" name="cellphone" value="(585) 271-8888">
<br>
<br> Office phone:
<br>
<input required type="tel" name="officephone" value="(585) 271-8887">
<br>
<br> Fax:
<br>
<input type="tel" name="fax" value="(585) 271-8886">
<br>
<br> City:
<br>
<input required type="text" name="city" value="City">
<br>
<br> State:
<br>
<input required type="text" name="state" value="New York">
<br>
<br> Requester title:
<br>
<input required type="text" name="requester" value="Requester title">
<br>
<br>
<br>
<button (click)="changeTest()">Change Valid State</button>
<div *ngIf="newUserInfoValidState; else allowOrgInput">
<!-- (click)='ngSubmit' -->
<!-- <a (click)='displaySibling()' routerLinkActive='router-link-active'>
<button autofocus class="next-button">Next</button>
</a> -->
<a [routerLink]="['../',{ outlets: { newuserorginfo: ['newuserorginfo'] } } ]" routerLinkActive='router-link-active'>
<button autofocus class="next-button">Next</button>
</a>
</div>
<ng-template #allowOrgInput>
<a>
<button autofocus href="#" class="next-button" disabled>Next</button>
</a>
</ng-template>
</form>
</div>
<router-outlet></router-outlet>
<router-outlet name="newuserorginfo"></router-outlet>
这是我的其他相关stackoverflow question。