Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Michael De Abreu
Michael De Abreu

Posted on

     

Input-Set pattern for Widgets in Angular

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>);}
Enter fullscreen modeExit fullscreen mode

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;}
Enter fullscreen modeExit fullscreen mode

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;}}
Enter fullscreen modeExit fullscreen mode

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;}}
Enter fullscreen modeExit fullscreen mode

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;}}
Enter fullscreen modeExit fullscreen mode

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)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

I'm a Software Engineer working as Frontend. I'll talk here about my experiences.
  • Joined

More fromMichael De Abreu

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp