假设我有一个名为import Lst.Aux
object Main {
def main(args: Array[String]) = {
}
def makeList(l: Lst): List[l.Item] = {
(0 until l.size map l.get).toList
}
}
object Lst {
type Aux[I] = Lst {type Item = I}
}
trait Lst extends Any {
type Item
def get(index: Int): Item
}
final case class StringLst(size: Integer) extends AnyVal with Lst {
type Item = Char
def get(index: Int) = ???
}
的组件,该组件将在应用程序的各个位置使用,所以我使它尽可能通用,就像这样:
button.component.ts
ButtonComponent
button.component.html
import { Component, ViewEncapsulation, Input, Output, EventEmitter } from '@angular/core';
import { FormGroup } from '@angular/forms';
@Component({
selector: 'app-button',
templateUrl: './button.component.html',
styleUrls: ['./button.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class ButtonComponent{
@Input() group: FormGroup;
@Input() type: string;
@Input() description: string;
@Input() class: string;
@Input() callFunction: Function;
}
现在我的按钮是完全可定制的(理论上)。现在,我将其导入到一个名为<div [formGroup]="group">
<button type="{{ type }}" class="{{ class }}" (click)="callFunction()">{{ description }}</button>
</div>
的登录组件中。我希望我的按钮实例在单击时运行此特定功能:
login.component.ts
login()
要使按钮实例可见,我将引用添加到我的登录模板中,如下所示:
//imports
/**
* This component is rendered at the start of application, it provides the UI
* & functionality for the login page.
*/
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
/**
* This class is used to build a login form along with initialization of validators
* as well as authenticate the user, and reroute upon success
*/
export class LoginComponent implements OnInit, AfterContentInit{
@ViewChild('login', { read: ViewContainerRef }) login_button;
/**
* This property initializes the formGroup element.
*/
userForm: FormGroup;
/**
* The constructor initializes Router, FormBuilder, OauthService, LoggerService, ToastrService
* & TranslatePipe in the component.
*/
constructor(//initializations
) { }
/**
* This is the hook called on the initialization of the component, it initializes
* the form.
*/
ngOnInit() {
this.buildForm();
}
/**
* This method initialized the the formGroup element. Its properties and the validators.
*
* @method buildForm
* @return
*/
buildForm() {
// validations
});
}
/**
* This method returns the values of the form controls.
*
* @return
*/
get form() { return this.userForm.controls; }
/**
* This method is triggered on success, it reroutes the user to main page.
*
* @return
*/
onSuccess() {
let result = this.translate.transform("pages[login_page][responses][success]");
this.logger.info(result);
this.toastr.success(result);
this.router.navigate(['main']);
}
/**
* This method is triggered when user clicks log-in, it calls the aunthenication method
* from oauth service.
*
* @return
*/
login() {
this.oauth.authenticateUser(this.form.username.value, this.form.password.value, this.onSuccess.bind(this));
}
ngAfterContentInit() { //here I build my login button instance after init
this.buildLoginButton();
}
/**
* This function builds the login button, imports the ButtonComponent
*
*/
buildLoginButton(){
let data = {
type: "button",
class: "btn btn-primary px-4",
description: this.translate.transform("pages[login_page][login_form][buttons][login]"),
function: "login",
group: this.userForm
}
const inputFactory = this.resolver.resolveComponentFactory(ButtonComponent);
const loginButton = this.login_button.createComponent(inputFactory);
loginButton.instance.group = data.group;
loginButton.instance.type = data.type;
loginButton.instance.class = data.class;
loginButton.instance.description = data.description;
loginButton.instance.callFunction = function(){ //I call parent function using a static method
LoginComponent.executeMethod(data.function);
}
}
static executeMethod(someMethod){ //for my login button this should return this.login()
eval("this."+someMethod+"()");
}
}
现在我的按钮可见了,太好了!但是现在当我单击按钮时:
错误TypeError:this.login不是函数 在eval时(在push ../ src / app / views / login / login.component.ts.LoginComponent.executeMethod (login.component.ts:225)、: 1:6) 在Function.push ../ src / app / views / login / login.component.ts.LoginComponent.executeMethod中 (login.component.ts:225) 在ButtonComponent.loginButton.instance.callFunction(login.component.ts:179) 在Object.eval [作为handleEvent](ButtonComponent.html:2) 在handleEvent(core.js:10251) 在callWithDebugContext(core.js:11344) 在Object.debugHandleEvent [作为handleEvent](core.js:11047) 在dispatchEvent(core.js:7710) 在core.js:8154 在HTMLButtonElement。 (platform-browser.js:988)
如何使我的按钮在父组件中运行该函数,而不是在其自身内部查找该函数?我不想在<div #login></div>
中进行太多更改,以使其不那么通用,因为我还必须制作其他可能会运行其他功能的按钮。
有一个解决方案指出使用ButtonComponent
来解决这个问题,但是由于我将按钮EventEmitter
和{{1 }}
编辑完整的 login.component.html :
ts
答案 0 :(得分:4)
将此代码添加到button.component.ts
@Output() clickFunctionCalled = new EventEmitter<any>();
callFunction() {
this.clickFunctionCalled.emit();
}
button.template.html中没有变化
在html中使用应用程序按钮组件的位置添加此代码
<app-button (clickFunctionCalled)="callCustomClickFunction($event)"></app-button>
将其添加到login.component.ts
callCustomClickFunction() {
console.log("custom click called in login");
this.login();
}
基本上,从子组件发出click事件。在父组件中捕获事件并调用父组件的所需函数。 您也可以像这样直接调用父组件的函数
<app-button (clickFunctionCalled)="login($event)"></app-button>
在使用动态组件创建器创建按钮组件时,需要执行以下操作来绑定输出事件
loginButton.instance.clickFunctionCalled.subscribe(data => {
console.log(data);
});