如何正确地将函数传递给Angular2 / Typescript中的自定义指令?
我是Angular 2的新手.我正在从AngularJS升级我的应用程序,现在我正处于UI / UX开发的最后阶段.我有一个需要帮助的最后一个问题.先感谢您.
当前计划 >我有一个自定义指令TspFieldWidgetDirective,它接受多个输入,一个是函数@Input(‘onRefresh’)public refresh:Function;. 什么不起作用 >每次在浏览器中加载TspHeaderComponent模板时,它会产生对OnRefresh函数onCompanyChange的无限循环调用,当它只应被调用一次时,当选择框更改值时. 请注意 >该功能在Angular 5中从未起作用,它在AngularJS中运行得非常好. 代码片段如下: TSP-header.component.ts /* Method to change company of the company selector @param: id - string @return: none */ public onCompanyChange(id: string): void { if ((__env.debug && __env.verbose)) { console.log('Setting current_company_id to ' + id); } if (id !== undefined && id !== null) { // @TODO: Update user preference on server IF they have permission to change their default company this.cookies.set('preferences.current_company_id',id); this.core.app.current_user.preferences.current_company_id = id; this.core.initApp(); this.router.navigate(['/app/dashboard']); } } TSP-了header.html <!-- company changer --> <li> <tsp-field-widget type="company-select" [onRefresh]="onCompanyChange(id)" [showAvatar]="true" [fieldData]="core.app.current_user.preferences" fieldKey="current_company_id" [hideLabel]="true" [optionData]="core.app.session.base_companies"> </tsp-field-widget> </li> TSP-场widget.component.ts // Component class @Component({ selector: 'tsp-field-widget',templateUrl: './templates/tsp-field-widget.html' }) export class TspFieldWidgetComponent implements OnInit { public lang:any; // for i18n @Input() public type: string; // the field type @Input() public isRequired: boolean; // is the field required @Input() public isReadonly: boolean; @Input() public index: any; // index of ng-repeat @Input() public filterBy: any; // used in conjunction with ng-repeat @Input() public orderBy: any; // used in conjunction with ng-repeat @Input() public fieldData: any; // the record of ng-repeat @Input() public fieldKey: string; // the index of record - record[fieldKey] @Input() public placeVal: string; // the placeholder value of the field,usually used for selects and other dropdowns @Input() public pattern: string; // used for ng-pattern @Input() public prefix: string; // Text to display before title listings @Input() public recordId: any; // the ID of the record @Input() public label: string; // the label for the field for <label> tag @Input() public suffix: string; // sub label,usually placed below some label or title @Input() public optionData: any[]; // array of data used to populate selects or to store data values @Input() public showAvatar: boolean; // show the fields avatar @Input() public hideLabel: boolean; // show the fields <label> @Input() public showAdd: boolean; // show the add button (to add new record) @Input() public showTitle: boolean; // avatar type: show the name of the user @Input() public showDesc: boolean; // avatar type: show the name of the user // @Input() public isHighlighted:boolean; // default type: highlight text @Input() public numRows: string; // textarea: the number of rows of the text area @Input() public idKey: string; // select: the default ID key for option data - defaults to _id @Input() public titleKey: string; // select: the default title key for option data - defaults to title @Input() public descKey: string; // select: the default description key for option data - defaults to description @Input() public sliderType: string; // percent,amount or default,slider type @Input() public sliderMinValue: string; // slider type @Input() public sliderMaxValue: string; // slider type @Input() public sliderStepValue: string; // slider type @Input() public sliderOrientation: string; // slider type @Input() public dzOptions: any; // dropzone options @Input() public dzCallbacks: any; // dropzone callbacks @Input() public dzMethods: any; // dropzone methods @Input() public decimalPlaces: string; // tspFormat type @Input() public locale: string; // for dates and currency @Input() public format: string; // for dates @Input() public formatHours: string; // for dates @Input() public intervalMins: number; // for dates @Input() public owner: string; // used for module windows to determine the type of record to add @Input('onAdd') public add: Function; @Input('onEdit') public edit: Function; @Input('onToggle') public toggle: Function; @Input('onDelete') public delete: Function; @Input('onRefresh') public refresh: Function; constructor(private el: ElementRef,private cookies: TspCookiesService,public core: TspCoreService,private object: TspObjectService,public date: TspDateService) { this.lang = core.lang; this.date = date; } } TSP-场widget.html <div *ngIf="type=='company-select'"> <select class="company-select" class="form-control" [(ngModel)]="fieldData[fieldKey]" (change)="refresh({'id': fieldData[fieldKey]})" data-parsley-trigger="change"> <option [selected]="x[idKey] === fieldData[fieldKey]" *ngFor="let x of optionData" [ngValue]="x[idKey]"> {{x[titleKey]}} </option> </select> </div>
完成修复
tsp-field-widget.component.ts – 将所有类型为Function的@Inputs更改为@Ouput并初始化为EventEmitters.将所有带有evt的前缀替换为on,不允许作为@Output的前缀.添加了四个新方法,一旦触发事件就会调用这些方法.每个新方法都需要为args参数分配一个接口以保持一致性 // Component class @Component({ selector: 'tsp-field-widget',slider type @Input() public sliderMinValue: string; // slider type @Input() public sliderMaxValue: string; // slider type @Input() public sliderStepValue: string; // slider type @Input() public sliderOrientation: string; // slider type @Input() public dzOptions: any; // dropzone options @Input() public dzCallbacks: any; // dropzone callbacks @Input() public dzMethods: any; // dropzone methods @Input() public decimalPlaces: string; // tspFormat type @Input() public locale: string; // for dates and currency @Input() public format: string; // for dates @Input() public formatHours: string; // for dates @Input() public intervalMins: number; // for dates @Input() public owner: string; // used for module windows to determine the type of record to add @Output() public evtAdd = new EventEmitter(); @Output() public evtEdit = new EventEmitter(); @Output() public evtToggle = new EventEmitter(); @Output() public evtDelete = new EventEmitter(); @Output() public evtRefresh = new EventEmitter(); constructor(private el: ElementRef,public date: TspDateService) { this.lang = core.lang; this.date = date; } add(args: IAdd){ this.evtAdd.emit(args); } edit(args: IEdit){ this.evtEdit.emit(args); } toggle(args: IToggle){ this.evtToggle.emit(args); } delete(args: IDelete){ this.evtDelete.emit(args); } refresh(args: IRefresh){ this.evtRefresh.emit(args); } } tsp-field-widget.html – 无需更改 tsp-header.component.ts – 更新为传入包含函数所需值的对象. public onCompanyChange(args: IRefresh):void { if (args !== undefined){ if (args.id !== undefined && args.id !== null) { if ((__env.debug && __env.verbose)) { console.log('Setting current_company_id to ' + args.id); } // @TODO: Update user preference on server IF they have permission to change their default company this.cookies.set('preferences.current_company_id',args.id); this.core.app.current_user.preferences.current_company_id = args.id; this.core.initApp(); this.router.navigate(['/app/dashboard']); } } } tsp-header.html – 将onRefresh属性重命名为evtRefresh.为了防止无限循环,我用括号而不是括号包装evtRefresh属性来表示该属性是一个事件而不是一个对象.函数参数也必须是$event. <!-- company changer --> <li> <tsp-field-widget type="company-select" (evtRefresh)="onCompanyChange($event)" [showAvatar]="true" [fieldData]="core.app.current_user.preferences" fieldKey="current_company_id" [hideLabel]="true" [optionData]="core.app.session.base_companies"> </tsp-field-widget> </li> (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |