I am relatively new to Angular 2. I am currently in the process of upgrading my application from AngularJS and focusing on completing the UI/UX development. There is one final issue that I am seeking help with, and I appreciate any assistance provided.
Current Strategy
- I have created a custom directive called TspFieldWidgetDirective, which accepts multiple inputs, including a function
.@Input('onRefresh') public refresh: Function;
- The TspFieldWidgetDirective element can be utilized within various components to transform standard form fields.
- I have integrated the current directive as a select box within the template of the TspHeaderComponent.
- Upon changing the value of the select box, the
OnRefresh
function is invoked to refresh the application for updating the view based on the selection of a new company.
Issues Encountered
Every time the TspHeaderComponent template loads in the browser, it triggers an endless loop of calls to the
OnRefresh
function, specifically onCompanyChange, instead of being executed only once when the select box values change.When modifying the value of the select box from the browser (within the TspFieldWidgetDirective template -
), it results in the following error.(change)="refresh({'id': fieldData[fieldKey]})"
ERROR TypeError: _co.refresh is not a function
Note
- The functionality has never functioned correctly in Angular 5; however, it worked perfectly in AngularJS.
- All features work except passing a function as input to the directive.
Code Snippets Provided Below:
tsp-header.component.ts
/*
Method for changing the 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-field-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
... Additional Input Properties ...
constructor(private el: ElementRef,
private cookies: TspCookiesService,
public core: TspCoreService,
private object: TspObjectService,
public date: TspDateService) {
this.lang = core.lang;
this.date = date;
}
}
tsp-field-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>