{"id":2019,"date":"2017-05-07T20:05:06","date_gmt":"2017-05-07T20:05:06","guid":{"rendered":"http:\/\/salientsoft.co.uk\/?p=2019"},"modified":"2018-10-10T17:15:57","modified_gmt":"2018-10-10T17:15:57","slug":"angular-2-expressions-containing-observables-cause-null-glitch-on-page-display","status":"publish","type":"post","link":"https:\/\/salientsoft.co.uk\/?p=2019","title":{"rendered":"Angular 2 expressions containing observables cause null glitch on page display"},"content":{"rendered":"<p>The following expressions caused a brief glitch whereby <strong><i>null<\/i><\/strong> was displayed prior to the observable <em>locationsCount<\/em> emitting its value:-<\/p>\n<blockquote>\n<pre>&lt;span text-capitalize&gt;show all{{showAllActive ? ' ' + (locationsCount | async) : ''}}&lt;\/span&gt;<\/pre>\n<\/blockquote>\n<p>This makes sense as the observable with its async pipe, <em>| async<\/em> , which handles the observable, is part of a string expression. In other cases where the observable is e.g. a returned list, then you would just get an empty list with no entries. However in this case, Angular needed to evaluate and display the expression and so <u>null<\/u> was briefly displayed instead of the value of <em>locationsCount<\/em>.<\/p>\n<p>The easiest way around this is to use a logical<strong><em> or<\/em><\/strong> which acts as a null coalescing operator in JavaScript\/TypeScript, to replace the null with a suitable constant string:-<\/p>\n<blockquote>\n<pre>&lt;span text-capitalize&gt;show all{{showAllActive ? ' ' + (locationsCount | async)||' ' : ''}}&lt;\/span&gt;<\/pre>\n<\/blockquote>\n<p>The use of<em> (locationsCount | async) || \u2018 \u2018<\/em>&#160; checks the first operand regardless of type, and if it is falsey, the second operand is taken. This is explained in <a href=\"http:\/\/stackoverflow.com\/questions\/476436\/is-there-a-null-coalescing-operator-in-javascript\">this post here<\/a>.<\/p>\n<p>An alternative, a more complex solution which also worked in my case and may be interesting in other cases, is to concatenate the observable with another observable which emits a constant string using <a href=\"http:\/\/reactivex.io\/rxjs\/class\/es6\/Observable.js~Observable.html#static-method-of\">Observable.of()<\/a>. The <em>concat<\/em> method emits all the values from each of the passed observables in turn, proceeding to the next one when an observable closes, as detailed in the <a href=\"http:\/\/reactivex.io\/rxjs\/class\/es6\/Observable.js~Observable.html#instance-method-concat\">RxJS api docs here<\/a>. Therefore, the constant observable emits a value and completes\/closes immediately which prevents the null glitch, followed by the locationsCount observable when it finally emits a value (which came from a mapped http api call):-<\/p>\n<p>initial version without constant observable:-<\/p>\n<blockquote>\n<pre>this.locationsCount = this.locationsAutoCompleteService.getLocationsCount()<br \/>  .map(count =&gt; {<br \/>    let countString: string = this.formatLocationsCount(count);<br \/>    return countString;<br \/>  });<\/pre>\n<\/blockquote>\n<p>Alternative version with concatenated constant observable:-<\/p>\n<blockquote>\n<pre>this.locationsCount = Observable.of(' ').concat(<br \/>    this.locationsAutoCompleteService.getLocationsCount()<br \/>    .map(count =&gt; {<br \/>      let countString: string = this.formatLocationsCount(count);<br \/>      return countString;<br \/>    })<br \/>  );<\/pre>\n<\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>The following expressions caused a brief glitch whereby null was displayed prior to the observable locationsCount emitting its value:- &lt;span text-capitalize&gt;show all{{showAllActive ? &#8216; &#8216; + (locationsCount | async) : &#8221;}}&lt;\/span&gt; This makes sense as the observable with its async pipe, | async , which handles the observable, is part of a string expression. In [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[198],"tags":[40,16],"_links":{"self":[{"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/2019"}],"collection":[{"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2019"}],"version-history":[{"count":12,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/2019\/revisions"}],"predecessor-version":[{"id":2032,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/2019\/revisions\/2032"}],"wp:attachment":[{"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2019"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2019"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2019"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}