Intro
If you read my last post, you should know what a Widget is, if you haven't already, do it now, I'llawait.
await Reader.read('
Widgets and components');
Now you know what Widgets should be. I tried to keep it simple for the first implementation, but I'm really turning my head around this. The thing is, React is a JavaScript pure framework and with JSX allow us to do things that we can't made with plain HTML templates, nevertheless, Typescript allow us for things that JavaScript does not, at the very least, it seems to allow that. Likeprivate properties. With that in mind, I'll try to explain why you should use private properties inside a Widget and how to manage the data entry in a better way.
The situation
Following the comparative with React from the last post, when theprops
are send to acomponent
, most of the the time we are getting it following the destructive pattern, allowing to do things like:
interfaceIUser{firstname:string;lastname:string;age:number;}exportfunctionusersList({users=[]}:{IUser[]}){return(<ul> users.map(user => userDetails(user));</ul>)}functionuserDetails({firstname,lastname,age}:IUser){return(<li><span>{firstname}{lastname}</span>have{age} years old</li>);}
I think this looks good, because it allow us to be explicit about what we want to show, and how to show it.
In Angular, we just@Input
the data that we want to get from the outside.
// user.tsinterfaceIUser{firstname:string;lastname:string;age:number;}// user-list.widget.tsimport{Component,Input}from'@angular/core';@Component({selector:'my-user-list',template:` <ul> <li *ngFor="let user of users"> <my-user-details [user]=user><my-user-details> </li> </ul> `})exportclassUserListWidget{@Input()publicusers:IUser[];}// user-details.widget.tsimport{Component,Input}from'@angular/core';@Component({selector:'my-user-details',template:`<span>{{user.firstname}} {{user.lastname}}</span> has {{user.age}} years old`,})exportclassUserDetailsWidget{@Input()publicuser:IUser;}
This is right, as Widgets are suppose to display data, and they shouldonly concern should be how to display that data. But we need a better way to organize how we show that data correctly in the template.
I like the approach from React in that sense. Don't get me wrong, I love Angular. But JSX allow us to do something nicer than dotter properties, destructive assignment.
Solution proposal
Now that is being clearer that React have a somewhat advantage above us, we as Angular developers need to propose a solution to be even, using features that are being bringed by Typescript,private properties. I know that Typescript is compiled to JavaScript, and JavaScript doesn't have such things, but, we'll do as we don't care.
Also, we will use a ES6set
feature. This allow us to have properties that can be set, but cannot be read.
Introducing@input set
import{Component,Input}from'@angular/core';@Component({selector:'my-user-details',template:`<span>{{firstname}} {{lastname}}</span> has {{age}} years old`,})exportclassUserDetailsWidget{private_user:IUser;@Input()publicsetuser(value:User):void{this._user=value;}}
OK. We learn we can set to private properties, but that does not quite allow us to show the properties in the template. Technically JavaScript only have properties, so we could bind to the private property, but we shouldnever bind a private property to the template, as the AOT compiler would throw.
Introducingtemplate get
@Component({selector:'my-user-details',template:`<span>{{firstname}} {{lastname}}</span> has {{age}} years old`,})exportclassUserDetailsWidget{private_user:IUser;@Input()publicsetuser(value:IUser){this._user=value;}publicgetfirstname():string{returnthis._user.firstname;}publicgetlastname():string{returnthis._user.lastname;}publicgetage():age{returnthis._user.age;}}
This actually works as expected. Allowing a better control over the data that are being displayed in the template, and how to expose it. Also, it would even allow us to do certain things, to maintain the code in a better way.
@Component({selector:'my-user-details',template:`<span>{{fullname}}</span> has {{age}} years old`,})exportclassUserDetailsWidget{private_user:IUser;@Input()publicsetuser(value:IUser){this._user=value;}publicgetfullname():string{return`${this._user.firstname}${this._user.lastname}`;}publicgetage():number{returnthis._user.age;}}
However,template get
as showed here have certain issues, but I'll explain everything about those issues properly in other post.
Example
For this, I made a little Plunker that expose the use case.Here
Thanks you
As always, thank you for reading this long. I hope you like it, and I am really looking forward to read your thoughts in the comments section.
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse