{"id":2052,"date":"2024-05-01T11:29:34","date_gmt":"2024-05-01T18:29:34","guid":{"rendered":"https:\/\/www.angulartraining.com\/daily-newsletter\/?p=2052"},"modified":"2024-05-01T11:29:34","modified_gmt":"2024-05-01T18:29:34","slug":"signals-custom-equality-functions","status":"publish","type":"post","link":"https:\/\/www.angulartraining.com\/daily-newsletter\/signals-custom-equality-functions\/","title":{"rendered":"Signals custom equality functions"},"content":{"rendered":"\n<p>Angular Signals are growing almost every day with new features and new ways of building Angular applications. If you&#8217;re still unsure about signals and want to catch up, you can watch this <a href=\"https:\/\/www.youtube.com\/watch?v=9tC9Vf4zb8k\" target=\"_blank\" rel=\"noopener\" title=\"\">Angular Signals workshop recording on Youtube<\/a> or sign up for my continuously updated <a href=\"https:\/\/courses.angulartraining.com\/course\/angular-signals\" target=\"_blank\" rel=\"noopener\" title=\"\">Angular Signals course<\/a>.<\/p>\n\n\n\n<p>Today, let&#8217;s explore how Angular determines if the value of a signal has changed. If we create the following signal with a default value of &#8220;Hello&#8221;:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"283\" height=\"32\" src=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/05\/image.png\" alt=\"\" class=\"wp-image-2053\" style=\"width:322px;height:auto\"\/><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>Then calling <code>name.set(\"Hello\")<\/code> does not trigger any updates for any of the consumers of our <code>name<\/code> signal. That&#8217;s because Angular compares the &#8220;new&#8221; value with the previous one using a <code>===<\/code> comparison, and <code>\"Hello\" === \"Hello\"<\/code> is true, so Angular doesn&#8217;t trigger any change.<\/p>\n\n\n\n<p>What about objects? When comparing objects with <code>===<\/code>, we&#8217;re comparing references, meaning &#8220;Are the two variables pointing at the same object?&#8221; We can verify that easily with a few lines of Javascript running in a browser console:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"230\" height=\"300\" src=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/05\/image-1.png\" alt=\"\" class=\"wp-image-2054\"\/><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>This leads us to the custom <a href=\"https:\/\/angular.dev\/guide\/signals#signal-equality-functions\" target=\"_blank\" rel=\"noopener\" title=\"\">signal equality function<\/a>. If we want to do a deep comparison instead of just comparing references, we can instruct Angular to do so by providing our own comparison function. Here is the example used by the Angular team:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"900\" height=\"239\" src=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/05\/image-2.png\" alt=\"\" class=\"wp-image-2055\" style=\"width:682px;height:auto\" srcset=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/05\/image-2.png 900w, https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/05\/image-2-300x80.png 300w, https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/05\/image-2-768x204.png 768w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>Of course, we don&#8217;t need lodash to implement custom equality functions. For example, we want to create a signal that only emits updates when the current user ID changes. We don&#8217;t care if the user&#8217;s name or email changes, just the ID (which would indicate that a new user logged in, most likely):<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"702\" height=\"174\" src=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/05\/image-3.png\" alt=\"\" class=\"wp-image-2056\" srcset=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/05\/image-3.png 702w, https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/05\/image-3-300x74.png 300w\" sizes=\"auto, (max-width: 702px) 100vw, 702px\" \/><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>With this approach, the signal doesn&#8217;t trigger any updates if we change values that aren&#8217;t the ID. For instance, we can secretly turn our user into Batman (and note that I do create a new object by making a copy of the current one, which would make <code>===<\/code> return false):<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"811\" height=\"91\" src=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/05\/image-4.png\" alt=\"\" class=\"wp-image-2057\" srcset=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/05\/image-4.png 811w, https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/05\/image-4-300x34.png 300w, https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/05\/image-4-768x86.png 768w\" sizes=\"auto, (max-width: 811px) 100vw, 811px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>And yet my user remains known as Bruce after turning him into Batman (<a href=\"https:\/\/stackblitz.com\/edit\/at-signal-equality?file=src%2Fmain.ts\" target=\"_blank\" rel=\"noopener\" title=\"\">full example here on Stackblitz<\/a>):<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"284\" height=\"303\" src=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/05\/image-5.png\" alt=\"\" class=\"wp-image-2058\" srcset=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/05\/image-5.png 284w, https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/05\/image-5-281x300.png 281w\" sizes=\"auto, (max-width: 284px) 100vw, 284px\" \/><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Why use custom equality functions?<\/h3>\n\n\n\n<p>Performance could be one thing: if we have a signal that stores an object and know that the only change we make to that object is one or two specific properties, then creating a custom equality function on these properties would make perfect sense. Even more so if the properties are in nested objects, though I wouldn&#8217;t recommend using deeply nested objects as signal values, keeping our values as flat as possible instead.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Angular Signals are growing almost every day with new features and new ways of building Angular applications. If you&#8217;re still unsure about signals and want to catch up, you can watch this Angular Signals workshop recording on Youtube or sign up for my continuously updated Angular Signals course. Today, let&#8217;s explore how Angular determines if [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,29],"tags":[],"class_list":["post-2052","post","type-post","status-publish","format-standard","hentry","category-angular","category-signals"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/posts\/2052","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/comments?post=2052"}],"version-history":[{"count":2,"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/posts\/2052\/revisions"}],"predecessor-version":[{"id":2060,"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/posts\/2052\/revisions\/2060"}],"wp:attachment":[{"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/media?parent=2052"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/categories?post=2052"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/tags?post=2052"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}