{"id":1954,"date":"2024-02-01T14:54:41","date_gmt":"2024-02-01T22:54:41","guid":{"rendered":"https:\/\/www.angulartraining.com\/daily-newsletter\/?p=1954"},"modified":"2024-02-01T14:54:42","modified_gmt":"2024-02-01T22:54:42","slug":"5-tips-for-strictly-typed-reactive-forms","status":"publish","type":"post","link":"https:\/\/www.angulartraining.com\/daily-newsletter\/5-tips-for-strictly-typed-reactive-forms\/","title":{"rendered":"5 tips for Strictly Typed Reactive Forms"},"content":{"rendered":"\n<p>Forms can be a very complex part of any web application, and today, I will cover some useful tips and tricks for using Reactive Forms with strict types.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Use <code>nonNullable: true<\/code> to restore default values on reset<\/strong><\/li>\n<\/ol>\n\n\n\n<p>Form controls and groups are nullable by default in Angular, which means that the following example of <code><a href=\"https:\/\/blog.angulartraining.com\/5-tips-on-using-angular-formcontrol-710ca338b896\" target=\"_blank\" rel=\"noopener\" title=\"\">FormControl<\/a><\/code> value isn&#8217;t of type <code>string<\/code>:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"464\" height=\"30\" src=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image.png\" alt=\"\" class=\"wp-image-1957\" srcset=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image.png 464w, https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-300x19.png 300w\" sizes=\"auto, (max-width: 464px) 100vw, 464px\" \/><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>Instead, if you try to read <code>email.value<\/code>, you&#8217;ll see that the type is <code>string<\/code> or <code>null<\/code>. Why would that be the case since we have a default value? That&#8217;s because the form can be reset with a <code>&lt;button type=\"reset\"><\/code> on the form or by calling <code>email.reset()<\/code>, for instance.<\/p>\n\n\n\n<p>The trick then is to make that control non nullable by adding the following option:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"696\" height=\"30\" src=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-1.png\" alt=\"\" class=\"wp-image-1958\" style=\"width:840px;height:auto\" srcset=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-1.png 696w, https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-1-300x13.png 300w\" sizes=\"auto, (max-width: 696px) 100vw, 696px\" \/><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>Now, when the form gets reset, <code>email.value<\/code> is equal to <code>\"test2@gmail.com\"<\/code>, which is perfect in several different form scenarios, such as an edit form, where we don&#8217;t want to &#8220;lose&#8221; the previous values, but just &#8220;reset&#8221; to those values.<\/p>\n\n\n\n<p><strong>2. Using non-nullable form controls at scale<\/strong><\/p>\n\n\n\n<p>If we want to apply that same config to several form controls, we can put them in a <code>FormGroup<\/code> and pass that same <code>nonNullable: true<\/code> option to the <code>FormGroup<\/code> constructor instead of specifying it for every single control. But what if we use the <a href=\"https:\/\/www.angulartraining.com\/daily-newsletter\/using-formbuilder-or-formcontrol\/\" target=\"_blank\" rel=\"noopener\" title=\"\"><code>FormBuilder<\/code> service<\/a>? <\/p>\n\n\n\n<p>Then we can use the following syntax:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"437\" height=\"182\" src=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-2.png\" alt=\"\" class=\"wp-image-1959\" srcset=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-2.png 437w, https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-2-300x125.png 300w\" sizes=\"auto, (max-width: 437px) 100vw, 437px\" \/><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p><strong>3. How to define the type of a <code>FormControl<\/code> with no default value? <\/strong><\/p>\n\n\n\n<p>If we do something like this:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"351\" height=\"34\" src=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-3.png\" alt=\"\" class=\"wp-image-1960\" srcset=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-3.png 351w, https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-3-300x29.png 300w\" sizes=\"auto, (max-width: 351px) 100vw, 351px\" \/><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>We&#8217;re in trouble because Typescript will infer the type of <code>password.value<\/code> is <code>null<\/code>. Instead, we use generics and a <a href=\"https:\/\/www.angulartraining.com\/daily-newsletter\/union-types-in-typescript\/\" target=\"_blank\" rel=\"noopener\" title=\"\">union type<\/a> to specify the expected type for that value, here <code>string<\/code> or <code>null<\/code>:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"506\" height=\"26\" src=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-4.png\" alt=\"\" class=\"wp-image-1961\" srcset=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-4.png 506w, https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-4-300x15.png 300w\" sizes=\"auto, (max-width: 506px) 100vw, 506px\" \/><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p><strong>4. How to read the values of disabled form controls?<\/strong><\/p>\n\n\n\n<p>In complex forms, it is very common that some controls are enabled\/disabled based on some condition. For instance, if the user selects the country &#8220;USA, &#8221; we might enable a state dropdown with the US states in it and disable it for other countries.<\/p>\n\n\n\n<p>When a control is disabled, its value doesn&#8217;t appear as part of the form group value. Here is an example where age is obviously equal to 21, but since that control is disabled, <code>formGroup.value<\/code> doesn&#8217;t return it:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"290\" height=\"210\" src=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-5.png\" alt=\"\" class=\"wp-image-1962\"\/><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>The workaround here is to use <code>formGroup.getRawValue()<\/code>, which will return everything, including disabled control values:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"245\" height=\"251\" src=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-6.png\" alt=\"\" class=\"wp-image-1963\" srcset=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-6.png 245w, https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-6-60x60.png 60w\" sizes=\"auto, (max-width: 245px) 100vw, 245px\" \/><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>You can see that <a href=\"https:\/\/stackblitz.com\/edit\/at-typed-forms?file=src%2Fmain.ts\" target=\"_blank\" rel=\"noopener\" title=\"\">example in action on Stackblitz here<\/a>.<\/p>\n\n\n\n<p><strong>5. How to handle dynamic forms where we don&#8217;t know which controls will be present ahead of time?<\/strong><\/p>\n\n\n\n<p>In some cases, forms can be completely different depending on the type of user, country, etc. As a result, we don&#8217;t know whether a control will be present or not at runtime. We can define that uncertainty in Typescript using the optional operator <code>?<\/code> when we define the type of our form:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"613\" height=\"399\" src=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-7.png\" alt=\"\" class=\"wp-image-1964\" srcset=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-7.png 613w, https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-7-300x195.png 300w\" sizes=\"auto, (max-width: 613px) 100vw, 613px\" \/><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>In the above code, <code>password<\/code> is defined as optional in our interface, meaning that the compiler will not throw an error if we remove that control later.<\/p>\n\n\n\n<p>If your form is 100% dynamic and handling proper types for each scenario would be a nightmare, you can use the more flexible <code><a href=\"https:\/\/angular.io\/guide\/typed-forms#formrecord\" target=\"_blank\" rel=\"noopener\" title=\"\">FormRecord<\/a><\/code> instead of <code>FormGroup<\/code>:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"749\" height=\"85\" src=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-8.png\" alt=\"\" class=\"wp-image-1965\" srcset=\"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-8.png 749w, https:\/\/www.angulartraining.com\/daily-newsletter\/wp-content\/uploads\/2024\/02\/image-8-300x34.png 300w\" sizes=\"auto, (max-width: 749px) 100vw, 749px\" \/><\/figure>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>Forms can be a very complex part of any web application, and today, I will cover some useful tips and tricks for using Reactive Forms with strict types. Form controls and groups are nullable by default in Angular, which means that the following example of FormControl value isn&#8217;t of type string: Instead, if you try [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[22],"tags":[],"class_list":["post-1954","post","type-post","status-publish","format-standard","hentry","category-forms"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/posts\/1954","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=1954"}],"version-history":[{"count":4,"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/posts\/1954\/revisions"}],"predecessor-version":[{"id":1967,"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/posts\/1954\/revisions\/1967"}],"wp:attachment":[{"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/media?parent=1954"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/categories?post=1954"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.angulartraining.com\/daily-newsletter\/wp-json\/wp\/v2\/tags?post=1954"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}