请考虑其模板包含文件输入的组件。可以通过调用公共open()
方法来打开输入,该方法触发对输入nativeElement
的点击。
@Component({
selector: 'child',
template: '<input type="file" #input/>',
})
export class ChildComponent {
@ViewChild('input')
public input: ElementRef;
public open(): void {
console.log('OPENING THE FILE INPUT');
this.input.nativeElement.click();
}
}
此ChildComponent
在ParentCompenent
中被调用,它在多个上下文中调用ChildComponent.open()
,如下所示:
@Component({
selector: 'parent',
template: '<child></child>',
})
export class ParentComponent {
@ViewChild(ChildComponent)
public child: ChildComponent;
constructor( private parentService: ParentService ) {
}
public openChildInput(): void {
// This works.
// Output:
// OPENING THE FILE INPUT
// The file input opens
this.child.open();
}
public waitAndOpenChildInput(): void {
parentService.wait()
.subscribe( () => {
// This does not work.
// Output:
// "OPENING THE FILE INPUT"
// The file input DOES NOT open...
this.child.open();
})
}
}
在两种情况下,调用open()
方法似乎都可以工作(如console.log
所示);但是从订阅中调用时,文件输入似乎不愿意打开自己。
任何想法为何? 预先感谢...
答案 0 :(得分:3)
出于安全原因,现代浏览器无法以编程方式在文件输入上调用date_counter
事件-除非,该事件发生在用户互动期间。否则,网站和广告可能会通过文件对话框向用户发送垃圾邮件,而无需他们与页面进行交互,例如让他们在不知不觉中上传文件。
使用Observable的问题在于,如果它是异步的(即,使用click
调度程序时),则您离开用户交互上下文,浏览器将不会打开文件对话框。
您只能通过使Observable同步(实际上,几乎所有预设的Observable都是同步的)来解决此问题。如果您有一个HTTP请求,这将是不可能的,您必须进行look for alternatives for opening the file dialog(尽管我不确定其中任何一个是否可以在您的设置中使用)。
Here is an GitHub issue与您的问题类似,有一个解释:
因此[由于异步],从Chrome的角度来看,click()调用[...]并非由用户事件触发,因此被忽略。