{"id":5879,"date":"2024-02-20T12:11:08","date_gmt":"2024-02-20T17:11:08","guid":{"rendered":"https:\/\/ionic.io\/blog\/?p=5879"},"modified":"2024-02-20T21:19:40","modified_gmt":"2024-02-21T02:19:40","slug":"catching-up-with-the-latest-features-in-angular","status":"publish","type":"post","link":"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular","title":{"rendered":"Catching Up With The Latest Features In Angular"},"content":{"rendered":"\n<p>Angular is having a bit of a renaissance lately. With the move to standalone components, the Angular team has been on a roll shipping new features and improvements to the framework at such speed, it&#8217;s hard to believe this is the same Angular we\u2019ve come to know. With all these changes, you might be confused about what you <strong>need<\/strong> to update to or what&#8217;s been removed. Let&#8217;s look at a new modern Angular structure and start to adopt these new features.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">&nbsp;A New Primitive<\/h2>\n\n\n\n<p>With recent releases of Angular, the core team has introduced a new way to manage component state, Signals. Signals, having been <a href=\"https:\/\/www.solidjs.com\/tutorial\/introduction_signals\">popularized in SolidJS<\/a>, provide an API for managing state, and reacting to changes in that state. Angular has adapted Signals into the framework and have started to build a set of new features that utilize Signals as their cornerstone.<\/p>\n\n\n\n<p>The first feature is just a raw <code>signal<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-typescript\">import { Component, signal } from &#039;@angular\/core&#039;;\n\n@Component({\n  template: `\n    &lt;p&gt;The current count is {{count()}}&lt;\/p&gt;\n  `,\n  standalone: true,\n  imports: [],\n})\nexport class AppComponent {\n  count = signal(0);\n}<\/code><\/pre>\n\n\n\n<p>A <code>signal<\/code> is a function that takes an initial value and when invoked, returns the current value of the <code>signal<\/code>. In our component, we create a <code>signal<\/code> called count with an initial value of 0. Then to access that <code>signal<\/code>, we invoke it via <code>{{count()}}<\/code>. When rendered, this will display \u201c0\u201d. To change the value of the <code>signal<\/code>, we can use set or update:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-typescript\">import { Component, signal } from &#039;@angular\/core&#039;;\n\n@Component({\n  template: `\n    &lt;p&gt;The current count is {{count()}}&lt;\/p&gt;\n    &lt;button (click)=&quot;increment()&quot;&gt;Increment&lt;\/button&gt;\n    &lt;button (click)=&quot;decrement()&quot;&gt;Decrement&lt;\/button&gt;\n    &lt;button (click)=&quot;reset()&quot;&gt;Reset&lt;\/button&gt;\n  `,\n  standalone: true,\n  imports: [],\n})\nexport class AppComponent {\n  count = signal(0);\n\n  increment(){\n    this.count.update((currentValue) =&gt; ++currentValue);\n  }\n  decrement(){\n    this.count.update((currentValue) =&gt; --currentValue);\n  }\n  reset(){\n    this.count.set(0);\n  }\n}<\/code><\/pre>\n\n\n\n<p>Using update allows us to access the current value of the <code>signal<\/code>, and set allows us to set a new value without caring about the current value.&nbsp;<\/p>\n\n\n\n<p>In addition to just raw Signals, we also can utilize <code>computed<\/code> to create derived values. <code>computed<\/code> allows us to create a <code>signal<\/code> that is based on another <code>signal<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-typescript\">import { Component, computed, signal } from &#039;@angular\/core&#039;;\n\n@Component({\n  template: `\n    &lt;p&gt;The current count is {{count()}}&lt;\/p&gt;\n    &lt;p&gt;The current count doubled is {{doubled()}}&lt;\/p&gt;\n    &lt;button (click)=&quot;increment()&quot;&gt;Increment&lt;\/button&gt;\n    &lt;button (click)=&quot;decrement()&quot;&gt;Decrement&lt;\/button&gt;\n    &lt;button (click)=&quot;reset()&quot;&gt;Reset&lt;\/button&gt;\n  `,\n  standalone: true,\n  imports: [],\n})\nexport class AppComponent {\n  count = signal(0);\n  doubled = computed(() =&gt; this.count() * 2);\n  increment(){\n    this.count.update((currentValue) =&gt; ++currentValue);\n  }\n  decrement(){\n    this.count.update((currentValue) =&gt; --currentValue);\n  }\n  reset(){\n    this.count.set(0);\n  }\n}<\/code><\/pre>\n\n\n\n<p>Here, <code>doubled<\/code> is going to render double whatever count\u2019s value is. What\u2019s helpful here is that because Signals are reactive, when count changes, double will automatically update to reflect the new value.&nbsp;<\/p>\n\n\n\n<p>Finally, the last concept of Signals that we need to know about are <code>effects<\/code>. <code>effects<\/code> are functions that get invoked when the value of a <code>signal<\/code> is changed.<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-typescript\">import { Component, computed, effect, signal } from &#039;@angular\/core&#039;;\n\nexport class AppComponent {\n  count = signal(0);\n  doubled = computed(() =&gt; this.count() * 2);\n\n  constructor(){\n    effect(() =&gt; {\n      console.log(`The value of count has changed: ${this.count()}`)\n    })\n    effect(() =&gt; {\n      console.log(`The value of double has changed: ${this.doubled()}`)\n    })\n  }\n}<\/code><\/pre>\n\n\n\n<p>What\u2019s important to know here is that an <code>effect<\/code> will only run when the accessed <code>signal<\/code> is invoked. Meaning, if we only access <code>doubled<\/code>, the effect will only run when doubled changes.<\/p>\n\n\n\n<p>And with all of this, you now know all about Signals! Congrats, but there is so much more now that we know what Signals are. With this, the Angular team has been revisiting the component API that has been with us since Angular v2.0. These optional changes provide an improved developer experience and are based all on Signals!&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Signals for all the things<\/h2>\n\n\n\n<p>If you\u2019ve ever wanted to pass data into a component with Angular, you\u2019ve used the <code>@Input<\/code> decorator. When developers set data on the component itself, the data is then accessible to the template.&nbsp;<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-typescript\">import { Component, Input } from &#039;@angular\/core&#039;;\n\n@Component({\n  template: ``,\n  standalone: true,\n  imports: [],\n})\nexport class ChildComponent {\n  @Input()\n  passedData = &#039;foo&#039;;\n}<\/code><\/pre>\n\n\n\n<p>Now this works fine for data that we just need to display, it can become pretty limiting if we need to perform any other actions. This leads to an approach where setters\/getters are used in combination with the <code>@Input<\/code> in order to achieve this:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-typescript\">export class ChildComponent {\n  private _internalData = &#039;foo&#039;;\n\n  @Input()\n  get passedData() {\n    return this._internalData;\n  }\n\n  set passedData(val) {\n    this._internalData = val;\n    this.someOtherAction();\n  }\n  someOtherAction() {\n    console.log(`passedData has changed: ${this.passedData}`);\n  }\n}<\/code><\/pre>\n\n\n\n<p>This <em>works<\/em>, but it can be better. The setter for <code>passedData<\/code> acts the same way as an effect does in our previous example on Signals, so why not just use Signals instead? The Angular team agrees and has provided a new <code>input<\/code> API.&nbsp;<\/p>\n\n\n\n<p>Similar to <code>@Input<\/code>, the signal based approach lets users pass data into a component using the <code>signal<\/code> primitive. Meaning, not only can we access it in our template like a normal <code>signal<\/code>, we can also use an <code>effect<\/code> when that <code>input<\/code> has changed.&nbsp;<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-typescript\">export class ChildComponent {\n  passedData = input(&#039;foo&#039;);\n\n  constructor() {\n    effect(() =&gt; {\n      console.log(`passedData has changed: ${this.passedData()}`);\n    });\n  }\n}<\/code><\/pre>\n\n\n\n<p>We can also mark our <code>input<\/code> as <code>required<\/code> so that developers know they must set that data.<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-typescript\">export class ChildComponent {\n  passedData = input.required(&#039;foo&#039;);\n\n  constructor() {\n    effect(() =&gt; {\n      console.log(`passedData has changed: ${this.passedData()}`);\n    });\n  }\n}<\/code><\/pre>\n\n\n\n<p>Now it doesn\u2019t stop there, we also have a few more decorators that we use inside our components. Things like <code>@ViewChild<\/code> and <code>@Output <\/code>are also on their way to becoming signal-based.&nbsp;<\/p>\n\n\n\n<p>Just released, an implementation of <a href=\"https:\/\/github.com\/angular\/angular\/pull\/54283\">queries<\/a> provide a more consistent way of working with the DOM elements. <a href=\"https:\/\/github.com\/angular\/angular\/pull\/54217\">Outputs<\/a> have always been merged, but are still marked as private to the framework.<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-typescript\">import { Component, ElementRef, effect } from &#039;@angular\/core&#039;;\n\n@Component({\n  standalone: true,\n  template: `&lt;div #el&gt;&lt;\/div&gt;`,\n})\nexport class AppComponent {\n  divEl = viewChild.required&lt;ElementRef&lt;HTMLDivElement&gt;&gt;(&#039;el&#039;);\n\n  constructor(){\n    effect(() =&gt; {\n      \/\/ some mapping library\n      new Maps({\n        el: this.divEl.nativeElement\n      })\n    })\n  }\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Two Way Signals<\/h2>\n\n\n\n<p>Everything we\u2019ve seen here has been the building block for what we have next, a reactive version of <code>ngModel<\/code>. <code>ngModel<\/code> has been with us all the way back in the Angular v1.0 days, and for good reason. It\u2019s traditionally been used for handling form data binding, where text inputs can have their value bound to a variable, and on input, update that variable\u2019s value.&nbsp;<\/p>\n\n\n\n<p>Now with Signals, we can recreate <code>ngModel<\/code> using the same primitive that make up the rest of our API, Signals.<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-typescript\">@Component({\n  standalone: true,\n  selector: &#039;some-checkbox&#039;,\n  template: `\n    &lt;p&gt;Checked: {{ checked() }}&lt;\/p&gt;\n    &lt;button (click)=&quot;toggle()&quot;&gt;Toggle&lt;\/button&gt;\n  `,\n})\nexport class SomeCheckbox {\n  checked = model(false);\n\n  toggle() {\n    checked.update(c =&gt; !c);\n  }\n}\n\n@Component({\n  Signals: true,\n  selector: &#039;some-page&#039;,\n  template: `\n    &lt;some-checkbox [(checked)]=&quot;isAdmin&quot; \/&gt;\n  `,\n})\nexport class SomePage {\n  isAdmin = signal(false);\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Parting Thoughts<\/h2>\n\n\n\n<p>So, we got Signals for almost every new part of Angular, <code>input<\/code>, <code>output<\/code>, <code>viewChild<\/code>, and <a href=\"https:\/\/github.com\/angular\/angular\/pull\/54252\">model<\/a>! There\u2019s a lot of momentum around Angular at the moment, with Signals\u00a0in the middle of it. To get more detail and understand the future of Signals in Angular components, be sure to check out the current <a href=\"https:\/\/github.com\/angular\/angular\/discussions\/49682\">RFC on the subject<\/a>.\u00a0<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Angular is having a bit of a renaissance lately. With the move to standalone components, the Angular team has been on a roll shipping new features and improvements to the framework at such speed, it&#8217;s hard to believe this is the same Angular we\u2019ve come to know. With all these changes, you might be confused [&hellip;]<\/p>\n","protected":false},"author":5,"featured_media":5880,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"publish_to_discourse":"","publish_post_category":"","wpdc_auto_publish_overridden":"","wpdc_topic_tags":"","wpdc_pin_topic":"","wpdc_pin_until":"","discourse_post_id":"","discourse_permalink":"","wpdc_publishing_response":"","wpdc_publishing_error":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1,123],"tags":[60,278],"class_list":["post-5879","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-all","category-perspectives","tag-angular","tag-signals"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v23.0 (Yoast SEO v23.0) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Catching Up With The Latest Features In Angular - Ionic Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Catching Up With The Latest Features In Angular\" \/>\n<meta property=\"og:description\" content=\"Angular is having a bit of a renaissance lately. With the move to standalone components, the Angular team has been on a roll shipping new features and improvements to the framework at such speed, it&#8217;s hard to believe this is the same Angular we\u2019ve come to know. With all these changes, you might be confused [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular\" \/>\n<meta property=\"og:site_name\" content=\"Ionic Blog\" \/>\n<meta property=\"article:published_time\" content=\"2024-02-20T17:11:08+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-02-21T02:19:40+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2024\/02\/angular-feature-image-1-1024x512.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"512\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Mike Hartington\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@mhartington\" \/>\n<meta name=\"twitter:site\" content=\"@ionicframework\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Mike Hartington\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular#article\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular\"},\"author\":{\"name\":\"Mike Hartington\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/c8c92b04d526adb925ea514c619a267b\"},\"headline\":\"Catching Up With The Latest Features In Angular\",\"datePublished\":\"2024-02-20T17:11:08+00:00\",\"dateModified\":\"2024-02-21T02:19:40+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular\"},\"wordCount\":806,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2024\/02\/angular-feature-image-1.png\",\"keywords\":[\"Angular\",\"Signals\"],\"articleSection\":[\"All\",\"Perspectives\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular\",\"url\":\"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular\",\"name\":\"Catching Up With The Latest Features In Angular - Ionic Blog\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular#primaryimage\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2024\/02\/angular-feature-image-1.png\",\"datePublished\":\"2024-02-20T17:11:08+00:00\",\"dateModified\":\"2024-02-21T02:19:40+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular#primaryimage\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2024\/02\/angular-feature-image-1.png\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2024\/02\/angular-feature-image-1.png\",\"width\":2240,\"height\":1120},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/ionic.io\/blog\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Catching Up With The Latest Features In Angular\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/ionic.io\/blog\/#website\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"name\":\"ionic.io\/blog\",\"description\":\"Build amazing native and progressive web apps with the web\",\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/ionic.io\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/ionic.io\/blog\/#organization\",\"name\":\"Ionic\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"width\":1920,\"height\":854,\"caption\":\"Ionic\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/ionicframework\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/c8c92b04d526adb925ea514c619a267b\",\"name\":\"Mike Hartington\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2018\/08\/mike-headshot-2-smaller-150x150.png\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2018\/08\/mike-headshot-2-smaller-150x150.png\",\"caption\":\"Mike Hartington\"},\"description\":\"Director of Developer Relations\",\"sameAs\":[\"https:\/\/twitter.com\/mhartington\",\"https:\/\/x.com\/mhartington\"],\"url\":\"https:\/\/ionic.io\/blog\/author\/mike\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Catching Up With The Latest Features In Angular - Ionic Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular","og_locale":"en_US","og_type":"article","og_title":"Catching Up With The Latest Features In Angular","og_description":"Angular is having a bit of a renaissance lately. With the move to standalone components, the Angular team has been on a roll shipping new features and improvements to the framework at such speed, it&#8217;s hard to believe this is the same Angular we\u2019ve come to know. With all these changes, you might be confused [&hellip;]","og_url":"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular","og_site_name":"Ionic Blog","article_published_time":"2024-02-20T17:11:08+00:00","article_modified_time":"2024-02-21T02:19:40+00:00","og_image":[{"width":1024,"height":512,"url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2024\/02\/angular-feature-image-1-1024x512.png","type":"image\/png"}],"author":"Mike Hartington","twitter_card":"summary_large_image","twitter_creator":"@mhartington","twitter_site":"@ionicframework","twitter_misc":{"Written by":"Mike Hartington","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular#article","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular"},"author":{"name":"Mike Hartington","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/c8c92b04d526adb925ea514c619a267b"},"headline":"Catching Up With The Latest Features In Angular","datePublished":"2024-02-20T17:11:08+00:00","dateModified":"2024-02-21T02:19:40+00:00","mainEntityOfPage":{"@id":"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular"},"wordCount":806,"commentCount":0,"publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"image":{"@id":"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular#primaryimage"},"thumbnailUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2024\/02\/angular-feature-image-1.png","keywords":["Angular","Signals"],"articleSection":["All","Perspectives"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular#respond"]}]},{"@type":"WebPage","@id":"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular","url":"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular","name":"Catching Up With The Latest Features In Angular - Ionic Blog","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular#primaryimage"},"image":{"@id":"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular#primaryimage"},"thumbnailUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2024\/02\/angular-feature-image-1.png","datePublished":"2024-02-20T17:11:08+00:00","dateModified":"2024-02-21T02:19:40+00:00","breadcrumb":{"@id":"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular#primaryimage","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2024\/02\/angular-feature-image-1.png","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2024\/02\/angular-feature-image-1.png","width":2240,"height":1120},{"@type":"BreadcrumbList","@id":"https:\/\/ionic.io\/blog\/catching-up-with-the-latest-features-in-angular#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/ionic.io\/blog"},{"@type":"ListItem","position":2,"name":"Catching Up With The Latest Features In Angular"}]},{"@type":"WebSite","@id":"https:\/\/ionic.io\/blog\/#website","url":"https:\/\/ionic.io\/blog\/","name":"ionic.io\/blog","description":"Build amazing native and progressive web apps with the web","publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/ionic.io\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/ionic.io\/blog\/#organization","name":"Ionic","url":"https:\/\/ionic.io\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","width":1920,"height":854,"caption":"Ionic"},"image":{"@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/ionicframework"]},{"@type":"Person","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/c8c92b04d526adb925ea514c619a267b","name":"Mike Hartington","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2018\/08\/mike-headshot-2-smaller-150x150.png","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2018\/08\/mike-headshot-2-smaller-150x150.png","caption":"Mike Hartington"},"description":"Director of Developer Relations","sameAs":["https:\/\/twitter.com\/mhartington","https:\/\/x.com\/mhartington"],"url":"https:\/\/ionic.io\/blog\/author\/mike"}]}},"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2024\/02\/angular-feature-image-1.png","_links":{"self":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/5879","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/comments?post=5879"}],"version-history":[{"count":4,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/5879\/revisions"}],"predecessor-version":[{"id":5884,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/5879\/revisions\/5884"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/media\/5880"}],"wp:attachment":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/media?parent=5879"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/categories?post=5879"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/tags?post=5879"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}