Внедрение дочернего компонента для доступа к его свойствам в parent в Angular - PullRequest
0 голосов
/ 29 мая 2018

Моя цель - использовать внедрение зависимостей в дочернем компоненте для доступа к его свойствам в родительском компоненте.Я хотел бы заставить его работать как this .Как вы можете видеть, «второй дочерний элемент» в консоли и шаблон идет от второго дочернего элемента и отображается в родительском элементе.Это НЕ требует, чтобы селектор второго дочернего компонента был в шаблоне родителя.

Цель моего реального приложения (код ниже) состоит в том, чтобы я мог переключаться между истиной и ложью в РОДИТЕЛЕ, нажавкнопка "изменить действительное состояние" в РЕБЕНОКЕ ... несмотря на то, что ссылка на ребенка ведется только через розетку маршрутизатора.

Я выбрал это решение, потому что мне не пришлось использовать селектор компонента в родительском элементе для доступа к дочерним данным .... но я получаю сообщение об ошибке:

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 ниже).

Спасибо за любую помощь, которую вы можете предоставить.

Вот код моего фактического приложения: РОДИТЕЛЬСКИЙ КОМПОНЕНТ (Я закомментировал код, который исправил мою проблему с обменом данными, но вызывает ошибку):

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 &nbsp;
          <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 &nbsp;
            <i class="fa fa-chevron-right"></i>
          </h4>
        </li> -->
        <li [routerLink]="[{ outlets: { newuserorginfo: ['newuserorginfo'] } } ]" routerLinkActive='active'>
          <h4 class="font-weight-light">2 Organization &nbsp;
            <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 &nbsp;
              <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 &nbsp;
                <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 вопрос .

...