{"id":3135,"date":"2024-03-13T22:05:25","date_gmt":"2024-03-13T21:05:25","guid":{"rendered":"https:\/\/nguenkam.com\/blog\/?p=3135"},"modified":"2024-03-13T23:13:49","modified_gmt":"2024-03-13T22:13:49","slug":"angular-17-2-new-features-model-signal-inputs-clearscreen-define-option","status":"publish","type":"post","link":"https:\/\/nguenkam.com\/blog\/index.php\/2024\/03\/13\/angular-17-2-new-features-model-signal-inputs-clearscreen-define-option\/","title":{"rendered":"[Angular 17.2] &#8211; new features  : Signal &#038; Model inputs, clearScreen, define option"},"content":{"rendered":"\n<p>Let us list out the most important changes and new features in the minor versions Angular 17.2<\/p>\n\n\n\n<h4>Signal Inputs<\/h4>\n\n\n\n<p>Signal Inputs arrived in Angular 17.1. They fulfill the same tasks as the&nbsp;<code>@Input<\/code>&nbsp;decorator: Property Binding.<\/p>\n\n\n\n<p>&nbsp;A Signal Input is a simple function named&nbsp;<code>input()<\/code>. The new Property Binding syntax looks like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ @Input-Style (old)\nclass HolidayComponent {\n  @Input() username = '';\n  @Input({required: true}) holiday: Holiday | undefined;\n}\n\n\/\/ Signal Input (new)\nclass HolidayComponent {\n  username = input(''); \/\/ Signal&lt;string&gt;\n  holiday = input&lt;Holiday&gt;(); \/\/ Signal&lt;Holiday | undefined&gt;\n} <\/code><\/pre>\n\n\n\n<p>The property is of type\u00a0<code>Signal<\/code>, which makes it reactive by nature. Instead of\u00a0<code>ngOnChanges()<\/code>\u00a0and\u00a0<code>ngOnInit()<\/code>, we can consume changes with\u00a0<code>effect()<\/code>\u00a0or\u00a0<code>computed()<\/code> .<\/p>\n\n\n\n<p>The second addition is the additional&nbsp;<code>required()<\/code>&nbsp;function. It fixes the issue with&nbsp;<code>@Input({required: true})<\/code>, which always results in the union type including&nbsp;<code>undefined<\/code>&nbsp;and the actual type:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ required input. \n\/\/ Here, We dont need the including \"undefined Type\" anymore, like with the old syntax\nclass HolidayComponent {\n  username = input(''); \/\/ Signal&lt;string&gt;\n  holiday = input.required&lt;Holiday&gt;(); \/\/ Signal&lt;Holiday&gt;\n} \n\n@Component({\n  tempate: `&lt;app-holiday &#91;username]=\"username\" &#91;holiday]=\"holiday\" \/&gt;`\n})\nclass HolidayContainerComponent {\n  username = 'Konrad Weber';\n  holiday = createHoliday();\n}<\/code><\/pre>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>As we can see in the example above, the\u00a0<code>input()<\/code>\u00a0function returns a signal, that can be used in the template or in computed values (which would be the modern equivalent of\u00a0<code>ngOnChanges<\/code>).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Component({\r\n  standalone: true,\r\n  selector: 'ns-pony',\r\n  template: `\r\n    @if (ponyModel(); as ponyModel) {\r\n      &lt;figure>\r\n        &lt;img &#91;src]=\"imageUrl()\" &#91;alt]=\"ponyModel.name\" \/>\r\n        &lt;figcaption>&lt;\/figcaption>\r\n      &lt;\/figure>\r\n    }\r\n  `\r\n})\r\nexport class PonyComponent {\r\n  ponyModel = input&lt;PonyModel>();\r\n  imageUrl = computed(() => `assets\/pony-${this.ponyModel()!.color}.gif`);<\/code><\/pre>\n\n\n\n<p>we can also use the signal as the source of an observable, to trigger an action when the input changes. For example, to fetch data from a server:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>export class PonyComponent {\r\n  ponyService = inject(PonyService);\r\n  ponyId = input.required&lt;number>();\r\n  \/\/ entity fetched from the server every time the ponyId changes\r\n  ponyModel = toSignal(toObservable(this.ponyId)\r\n    .pipe(switchMap(id => this.ponyService.get(id))));\n\r\n  imageUrl = computed(() => `assets\/pony-${this.ponyModel()!.color}.gif`);<\/code><\/pre>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4>Model signal inputs<\/h4>\n\n\n\n<p>In the latest update of Angular 17.2, a new feature was introduced: model inputs. These inputs are built on writable signals and establish an input\/output pair that enables two-way bindings. <\/p>\n\n\n\n<p>In the example provided below, the signals in both components always have the same value, and we can increase this value by pressing on of the buttons<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ First Component\n@Component({\n  selector: 'app-counter',\n  standalone: true,\n  template: `&lt;button (click)=\"increase()\"&gt;Counter's button: {{ value() }}&lt;\/button&gt;`,\n})\nexport class CounterComponent {\n  value = model.required&lt;number&gt;();\n  increase() {\n    this.value.update((x) =&gt; x + 1);\n  }\n}\n\n\/\/ 2nd Component - Here we use the first component as the child-component\n@Component({\n  selector: 'app-wrapper',\n  standalone: true,\n  imports: &#91;CounterComponent],\n  template: `&lt;app-counter &#91;(value)]=\"count\" \/&gt;\n    &lt;button (click)=\"increase()\"&gt;Wrapper's button: {{ count() }}&lt;\/button&gt;`\n})\nexport class WrapperComponent {\n  count = signal(0);\n  increase() {\n    this.count.update((x) =&gt; x + 1);\n  }\n}<\/code><\/pre>\n\n\n\n<p>We can also bind an input element&#8217;s value to a writable signal by two-way data binding, using the &#8216;banana in the box&#8217; syntax&nbsp;<code>[(ngModel)]<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Component({\n  selector: 'app-root',\n  standalone: true,\n  imports: &#91;\n    FormsModule,\n  ],\n  template: `\n&lt;textarea\n  &#91;(ngModel)]=\"promptValue\"\n&gt;&lt;\/textarea&gt;`\n})\nexport class AppComponent {\n  promptValue = signal('');\n}<\/code><\/pre>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4>View queries and component queries as signals<\/h4>\n\n\n\n<p>With this improvement, we can query elements from the component&#8217;s template as signals: there are new&nbsp;<code>viewChild()<\/code>,&nbsp;<code>viewChildren()<\/code>,&nbsp;<code>contentChild()<\/code>&nbsp;and&nbsp;<code>contentChildren()<\/code>&nbsp;functions that return Signals.<\/p>\n\n\n\n<p><strong>PS: <\/strong><em>These are signal based versions of the&nbsp;<code>@viewChild<\/code>,&nbsp;<code>@viewChildren<\/code>,&nbsp;<code>@contentChild<\/code>&nbsp;and&nbsp;<code>@contentChildren<\/code>&nbsp;decorators:<\/em><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Component({\n  selector: 'app-vc-query-as-signal',\n  standalone: true,\n  template: `\n    &lt;button (click)=\"show()\"&gt;Show&lt;\/button&gt;\n    @if(visible()) {\n      &lt;div #id1&gt;Hi!&lt;\/div&gt;\n    }`,\n})\nclass VcQueryAsSignalComponent {\n  visible = signal(false);\n  divEl = viewChild&lt;ElementRef&lt;HTMLDivElement&gt;&gt;('id1'); \/\/ ?\n  effectRef = effect(() =&gt; {\n    console.log(this.divEl());\n  });\n  show() {\n    this.visible.set(true);\n  }\n}\n\n\/\/ First message on the console: undefined\n\/\/ The user clicks on the button\n\/\/ Second message on the console: _ElementRef {nativeElement: div}\n<\/code><\/pre>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4>Angular CLI: clearScreen option support<\/h4>\n\n\n\n<p>Angular can clear the screen before each re-build. we can enable this feature in&nbsp;<code>angular.json<\/code>, by setting the&nbsp;<code>clearScreen<\/code>&nbsp;builder option to&nbsp;<code>true<\/code>&nbsp;(it&#8217;s&nbsp;<code>false<\/code>&nbsp;by default):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ angular.json\n\n{\n  \"projects\": {\n    \"ng172\": {\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular-devkit\/build-angular:application\",\n          \"options\": {\n            \/\/ ? clear the screen before each re-build\n            \"clearScreen\": true,\n            \/\/ ...            <\/code><\/pre>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4>Angular CLI: &#8216;define&#8217; option for declaring global identifiers<\/h4>\n\n\n\n<p>The&nbsp;<code>application<\/code>&nbsp;builder supports the&nbsp;<code>define<\/code>&nbsp;option for declaring global identifiers. As these identifiers declared in&nbsp;<code>angular.json<\/code>, not in a&nbsp;<code>.ts<\/code>&nbsp;support, we can declare it for typescript using a&nbsp;<code>declare const<\/code>&nbsp;statement in&nbsp;<code>src\/types.d.ts<\/code>.<\/p>\n\n\n\n<p><strong>PS:<\/strong>  <em>We can use these identifiers as an alternate to the environment files in the future.<\/em><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ angular.json\n\n{\n  \"projects\": {\n    \"ng172\": {\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular-devkit\/build-angular:application\",\n          \"options\": {\n            \"define\": {\n              \/\/ the value must have a valid JSON syntax ?\n              \"CONSTANT_IN_ANGULAR_JSON\": \"{ 'text': 'This constant is defined in angular.json', 'number': 1 }\"\n            },\n            \/\/ ...<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ src\/types.d.ts\n\ndeclare const CONSTANT_IN_ANGULAR_JSON: { text: string; number: number };<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ component.ts\n\n@Component({\n  template: `\n    Text: {{ CONSTANT_IN_ANGULAR_JSON.text }}, \n    Number:{{ CONSTANT_IN_ANGULAR_JSON.number }}`,\n})\nexport class GlobalIdentifierComponent {\n  CONSTANT_IN_ANGULAR_JSON = CONSTANT_IN_ANGULAR_JSON;\n}\n<\/code><\/pre>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h5>Reference: <\/h5>\n\n\n\n<p><a href=\"https:\/\/dev.to\/this-is-angular\/\">https:\/\/dev.to\/this-is-angular\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Let us list out the most important changes and new features in the minor versions Angular 17.2 Signal Inputs Signal Inputs arrived in Angular 17.1. They fulfill the same tasks as the&nbsp;@Input&nbsp;decorator: Property Binding. &nbsp;A Signal Input is a simple function named&nbsp;input(). The new Property Binding syntax looks like this: The property is of type\u00a0Signal, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3139,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[37,5,83],"tags":[808,804,809,805,803,810,806,807],"_links":{"self":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/3135"}],"collection":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=3135"}],"version-history":[{"count":4,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/3135\/revisions"}],"predecessor-version":[{"id":3142,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/3135\/revisions\/3142"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/media\/3139"}],"wp:attachment":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=3135"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=3135"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=3135"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}