I'm using an Angular/.net application with .net6.0 framework, with Angular: 13.1.2, Node: 16.13.1 and EMCAScript 5.
I have the following person class in typescript.
export class Person {
private _name: string = '';
constructor() {
}
public get name(): string {
return this._name;
}
public set name(value: string) {
this._name = value;
}
}
While compiling the following person.model.js file is generated. But I'm under the impression the Object.defineProperties doesn't work.
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var Person = /** @class */ (function () {
function Person() {
this._name = '';
}
Object.defineProperty(Person.prototype, "name", {
get: function () {
return this._name;
},
set: function (value) {
this._name = value;
},
enumerable: true,
configurable: true
});
return Person;
}());
exports.Person = Person;
//# sourceMappingURL=person.model.js.map
Whenever I try to update my Reactive form using an object no data is updated. While I'm debugging I only notice the '_name' property in the 'Object.Keys' array.
this.personForm.get('person')?.patchValue(person);
Reactive form is defined the following way.
return formBuilder.group({
person: formBuilder.group({
name: [
'',
[
Validators.required
]
]
})
});
Whenever I update my class with 'Object.DefineProperty' the above code updating the Reactive form seems to work without problems. Also the 'Name' property seems to have been added to the 'Object.Keys' array.
export class Person {
private _name: string = '';
constructor() {
Object.defineProperty(this, 'name', {
set: function (value: string) {
this._name = value;
},
get: function () {
return this._name;
},
enumerable: true
})
}
}
Do I need to add the Object.defineProperties in the .ts file or is my application not using the generated .js files ?
EDIT:
Component
export class PersonComponent implements OnInit {
personForm!: FormGroup;
constructor(
private _fb: FormBuilder) {}
private CreateFormGroup(formBuilder: FormBuilder): FormGroup {
return formBuilder.group({
person: formBuilder.group({
name: [
'',
[
Validators.required
]
]
})
});
}
ngOnInit(): void {
this.personForm = this.CreateFormGroup(this._fb);
}
setPerson(person: Person) {
if (person != undefined) {
this.personForm.get('person')?.patchValue(person);
}
}
}
HTML:
<mat-card >
<mat-card-title>Person</mat-card-title>
<mat-card-content>
<form [formGroup]="personForm">
<div formGroupName="person">
<mat-form-field >
<input id="name" matInput aria-label="name" type="text" formControlName="name" autofocus required />
<mat-placeholder >name</mat-placeholder>
</mat-form-field>
</div>
<br />
</form>
</mat-card-content>
</mat-card>
<app-person-selection (personEvent)="setPerson($event)"></app-person-selection>
CodePudding user response:
TypeScript does transpiles the getter/setter into an equivalent Object.defineProperty
syntax.
But if you carefully look at the transpiled code, you will observe that the name
property is defined on Person.prototype
i.e on function's prototype, and not on the function itself.
// Transpiled code with v3.9.7
var Person = /** @class */ (function () {
function Person() {
this._name = '';
}
Object.defineProperty(Person.prototype, "name", { // <----
get: function () {
return this._name;
},
set: function (value) {
this._name = value;
},
enumerable: false,
configurable: true
});
return Person;
}());
Whereas in the 2nd scenario, wherein you manually define Object.defineProperty
, you are passing 1st argument as this
, and not Person.prototype.
// Transpiled code with v3.9.7
var Person = /** @class */ (function () {
function Person() {
this._name = '';
Object.defineProperty(this, 'name', { // <----
set: function (value) {
this._name = value;
},
get: function () {
return this._name;
},
enumerable: true
});
}
return Person;
}());
This is the reason why name
property is not visible within Object.keys
in 1st scenario (getter/setter), but is visible in the 2nd scenario. And for the same reason the patchValue
doesn't work as name
is not an object's own enumerable property.