我的子组件中有一个名为 files
的属性,它是 input type=file
. 使用该属性,我可以检查用户是否选择了要上传的文件,因此如果输入中没有文件,我可以禁用提交按钮 . 我的问题是,现在我在父组件中有提交按钮,因此当输入中有文件时,我无法检查属性 files
以启用按钮 .
那么,如何从父组件访问files属性并检查输入是否包含文件?
我已经尝试使用 @ViewChild
decorator与这样的东西 this.childComponent.files
但我得到了未定义 . 我也试过了 @Output
但是我无法让它发挥作用 .
编辑:添加代码
父组件TS:
import { Component, OnInit, ViewChild } from '@angular/core';
import { StepState } from '@covalent/core';
import { StepThreeComponent } from './step-three/step-three.component';
import { StepTwoComponent } from './step-two/step-two.component';
import { StepOneComponent } from './step-one/step-one.component';
@Component({
selector: 'app-user-verification',
templateUrl: './user-verification.component.html',
styleUrls: ['./user-verification.component.scss']
})
export class UserVerificationComponent implements OnInit {
@ViewChild(StepThreeComponent) stepThreeComponent: StepThreeComponent;
@ViewChild(StepTwoComponent) stepTwoComponent: StepTwoComponent;
@ViewChild(StepOneComponent) stepOneComponent: StepOneComponent;
checkFiles: any;
//EXECUTE ALL UPLOAD FUNCTIONS
uploadAllFiles() {
this.stepThreeComponent.uploadSingle();
this.stepOneComponent.uploadSingle();
this.stepTwoComponent.uploadSingle();
console.log('No FUnciona')
}
ngOnInit() {
this.checkFiles = this.stepOneComponent.files;
console.log(this.checkFiles)
}
}
父组件HTML:
<td-steps>
<td-step #step1 sublabel="Suba una copia de la parte delantera de su Cédula de Identidad" [active]="true" [disabled]="false" (activated)="activeStep1Event()" [state]="stateStep1" (deactivated)="deactiveStep1Event()">
<ng-template #head1 td-step-label><span>Foto de Cédula de Identidad (I)</span></ng-template>
<app-step-one></app-step-one>
</td-step>
<td-step #step2 [active]="true" label="Foto de Cédula de Identidad (II)" sublabel="Suba una copia de la parte trasera de su Cédula de Identidad" [state]="stateStep2" [disabled]="false" disableRipple>
<app-step-two></app-step-two>
</td-step>
<td-step #step3 label="Selfie con Cédula de Identidad" sublabel="Subir Selfie" [state]="stateStep3" [disabled]="true" [active]="true">
<app-step-three></app-step-three>
<ng-template td-step-actions>
<button [disabled]="!checkFiles" (click)="uploadAllFiles()">SUBIR TODO</button>
</ng-template>
</td-step>
</td-steps>
儿童组成部分TS:
import { Component } from '@angular/core';
import { UploadService } from '../../../services/upload.service';
import * as firebase from 'firebase/app';
import "firebase/storage";
import { Upload } from '../../../services/upload';
import * as _ from "lodash";
@Component({
selector: 'app-step-one',
templateUrl: './step-one.component.html',
styleUrls: ['./step-one.component.scss']
})
export class StepOneComponent {
selectedFiles: FileList;
currentUpload: Upload;
files: any;
disabled: any;
constructor(private upSvc: UploadService) { }
//Upload Service
detectFiles(event) {
this.selectedFiles = event.target.files;
}
uploadSingle() {
let uid = firebase.auth().currentUser.uid;
let file = this.files
this.currentUpload = new Upload(file);
this.upSvc.pushUpload(this.currentUpload, uid)
}
}
儿童组件HTML:
<div>
<div layout="row">
<md-input-container tdFileDrop [disabled]="disabled" (fileDrop)="files = $event" (click)="fileInput.inputElement.click()" (keyup.enter)="fileInput.inputElement.click()" (keyup.delete)="fileInput.clear()" (keyup.backspace)="fileInput.clear()" flex>
<input mdInput placeholder="select or drop files" [value]="files?.length ? (files?.length + ' files') : files?.name" [disabled]="disabled" readonly/>
</md-input-container>
<button md-icon-button *ngIf="files" (click)="fileInput.clear()" (keyup.enter)="fileInput.clear()">
<md-icon>cancel</md-icon>
</button>
<td-file-input class="push-left-sm push-right-sm" #fileInput [(ngModel)]="files" multiple [disabled]="disabled">
<md-icon>folder</md-icon>
<span class="text-upper">Browse...</span>
</td-file-input>
</div>
<div *ngIf="currentUpload">
<div class="progress">
<div class="progress-bar progress-bar-animated" [ngStyle]="{ 'width': currentUpload?.progress + '%' }"></div>
</div>
Progress: {{currentUpload?.name}} | {{currentUpload?.progress}}% Complete
</div>
</div>
EDIT #2:
HTML父母:
<app-step-one #StepOneComponent></app-step-one>
父母:
ngAfterViewInit() {
this.checkFiles = this.stepOneComponent.getFiles();
}
getFiles() {
this.checkFiles = this.stepOneComponent.getFiles();
console.log(this.checkFiles);
}
ts孩子补充道:
getFiles() {
return this.files
}
我也试过 this.stepOneComponent.files;
但它也没用 . 之后我在子组件中创建了 getFiles()
,看看我是否可以在输入中获取文件并且它有效 . 我能够从父组件执行 console.log()
并获取文件数据 . 但我需要做的是自动检查更改而不是按钮内的功能 .
编辑#3(重复):这个问题对我没有帮助,因为我需要自动检查更改而不是手动检查 .
1 回答
给你的子类一些公共元素,如
isValid
,也许一些$valid: BehaviorSubject<boolean>
可以通过父组件内部的@ViewChild
消费 .编辑:看到你的代码后,我相信你的@ViewChild实现是不正确的:
什么都不做 . 装饰器在用
#StepOneComponent
修饰的父组件标记中找不到任何内容 .在您的标记中,您需要:
在你的班上:
编辑更多:
是一个指向:
这是
SomeComponentClass
的一个实例,其选择器为child-component
. 您需要使用AfterViewInit的原因是子组件将不可用; from Angular's docs:在您的父类中,
@ViewChild(StepOneComponent) stepOneComponent: StepOneComponent;
不执行任何操作 .您的父级标记:
如果你解决了这些问题,那么你所做的就会奏效 .
编辑暴露属性getter
这里的诀窍是你绑定了
td-file-input
,ngModel
指向StepOneComponent
中的属性files
. 为了让自己设置一个更改侦听器,您需要做的就是利用files
的getter / setter .然后在您的父组件中: