{"id":2988,"date":"2021-01-18T10:00:00","date_gmt":"2021-01-18T15:00:00","guid":{"rendered":"https:\/\/www.mymiller.name\/wordpress\/?p=2988"},"modified":"2021-01-18T10:58:58","modified_gmt":"2021-01-18T15:58:58","slug":"angular-structural-directive-onsize","status":"publish","type":"post","link":"https:\/\/www.mymiller.name\/wordpress\/angular\/angular-structural-directive-onsize\/","title":{"rendered":"Angular Structural Directive onSize"},"content":{"rendered":"\n<p>Recently I needed to be able to switch between parts of my HTML based on the screen resolution.  This is something most web developers will run into needing to support Mobile and Desktop systems.  I got to thinking about it, and was thinking how nice it would be if *ngIf=&#8221;screen:sm&#8221; or something like that.  I mean wouldn&#8217;t it be great to have a nice directive to do this for you?<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">*onSize was born<\/h2>\n\n\n\n<p>Well wouldn&#8217;t it be nice if we had a *onSize directive that we could use everywhere to enable different elements as necessary?  <\/p>\n\n\n\n<p>Well I got to thinking about it, and sat down one night and came up with this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import {Directive, Input, OnDestroy, OnInit, TemplateRef, ViewContainerRef} from '@angular\/core';\nimport {BreakpointObserver, Breakpoints, BreakpointState} from \"@angular\/cdk\/layout\";\nimport {Subscription} from \"rxjs\";\n\n@Directive({\n  selector: '&#91;onSize]'\n})\nexport class OnSizeDirective implements OnDestroy{\n  private hasView = false;\n  private subscription: Subscription;\n  private _sizes:string&#91;] = &#91;];\n  private result: BreakpointState | undefined;\n\n  constructor(\n    private templateRef: TemplateRef&lt;any&gt;,\n    private viewContainer: ViewContainerRef,\n    private breakpointObserver: BreakpointObserver) {\n\n    this.subscription = this.breakpointObserver.observe(&#91;\n      Breakpoints.XSmall,\n      Breakpoints.Small,\n      Breakpoints.Medium,\n      Breakpoints.Large,\n      Breakpoints.XLarge\n    ]).subscribe(result =&gt; {\n      this.result = result;\n      this.updateView();\n    });\n  }\n\n\n  @Input() set onSize(sizes:string&#91;]) {\n    this._sizes = sizes;\n    this.updateView();\n  }\n\n  private updateView() {\n    let viewChange = false;\n\n    if(this.result != undefined) {\n      if ( (this.result.breakpoints&#91;Breakpoints.XSmall] &amp;&amp; this.containsSize(\"xs\"))\n            || (this.result.breakpoints&#91;Breakpoints.Small] &amp;&amp; this.containsSize(\"sm\"))\n            || (this.result.breakpoints&#91;Breakpoints.Medium] &amp;&amp; this.containsSize(\"md\"))\n            || (this.result.breakpoints&#91;Breakpoints.Large] &amp;&amp; this.containsSize(\"lg\"))\n            || (this.result.breakpoints&#91;Breakpoints.XLarge] &amp;&amp; this.containsSize(\"xl\"))) {\n        viewChange = true;\n      }\n    }\n\n    this.setView(viewChange);\n  }\n\n  setView(condition:boolean) {\n    if (condition &amp;&amp; !this.hasView) {\n      this.viewContainer.clear();\n      this.viewContainer.createEmbeddedView(this.templateRef);\n      this.hasView = true;\n    } else if (!condition &amp;&amp; this.hasView) {\n      this.viewContainer.clear();\n      this.hasView = false;\n    }\n  }\n\n  containsSize(size:string): boolean {\n    return this._sizes.filter(item =&gt; item === size).length &gt; 0;\n  }\n\n  ngOnDestroy(): void {\n    this.subscription.unsubscribe();\n  }\n}\n<\/code><\/pre>\n\n\n\n<p>So let&#8217;s start breaking this down.  First we need to create a directive:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ng g d directives\/on-size<\/code><\/pre>\n\n\n\n<p>Now we need to make this a structural directive and we do that be adding TemplateRef&lt;any&gt;  and ViewContainerRef to the constructor.  If you need more information on this, <a href=\"https:\/\/angular.io\/guide\/structural-directives#write-a-structural-directive\" data-type=\"URL\" data-id=\"https:\/\/angular.io\/guide\/structural-directives#write-a-structural-directive\">check here<\/a>. <\/p>\n\n\n\n<p>Next, we need to know what sizes you want to display under.  For this implementation we choose Extra Small(xs), Small(sm), Medium(md), Large(lg), and Extra Large(xl) as my sizes.  These come directly from the <a href=\"https:\/\/material.angular.io\/cdk\/layout\/api\" data-type=\"URL\" data-id=\"https:\/\/material.angular.io\/cdk\/layout\/api\">BreakpointObserver API<\/a>. <\/p>\n\n\n\n<p>Now we add the BreakpointObserver to the constructor.  Then we observe (), for all the types we are interested in. Make sure you save this subscription off so that you unsubscribe when the directive is destroyed.<\/p>\n\n\n\n<p>Now to make things simple we set an @Input set onSize()  to take a string array.  Whenever the BreakpointObserver or onSize() changes we call updateView() to check if we match on the screen size, if we do then call setView().<\/p>\n\n\n\n<p>setView() will check if we have the view and if the condition was met.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Creating an angular structural directive to operate on screen resolution.  <\/p>\n","protected":false},"author":1,"featured_media":2989,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"Angular Structural Directive onSize #angular #onSize #directive","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[281],"tags":[269],"series":[283],"class_list":["post-2988","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-angular","tag-angular","series-angular"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2021\/01\/plan-2092499_640.jpg?fit=640%2C435&ssl=1","jetpack-related-posts":[{"id":2657,"url":"https:\/\/www.mymiller.name\/wordpress\/angular\/angular-material-grid-layout-responsive\/","url_meta":{"origin":2988,"position":0},"title":"Angular Material Grid Layout Responsive","author":"Jeffery Miller","date":"December 16, 2019","format":false,"excerpt":"Angular Material is a powerful extension onto Angular for UI design. I personally fell in love with it before I ever used it. When I started using it I knew I would find things I would want to improve. Material Grid List is so handy to use and makes layouts\u2026","rel":"","context":"In &quot;Angular&quot;","block_context":{"text":"Angular","link":"https:\/\/www.mymiller.name\/wordpress\/category\/angular\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2019\/12\/grid-684983_640.jpg?fit=640%2C480&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2019\/12\/grid-684983_640.jpg?fit=640%2C480&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2019\/12\/grid-684983_640.jpg?fit=640%2C480&ssl=1&resize=525%2C300 1.5x"},"classes":[]},{"id":2511,"url":"https:\/\/www.mymiller.name\/wordpress\/angular\/angular-environment\/","url_meta":{"origin":2988,"position":1},"title":"Angular Environment","author":"Jeffery Miller","date":"March 11, 2019","format":false,"excerpt":"Building a website for today and tomorrow begins with Angular. Yes I am a proponent of Angular over many other client frameworks. Let's look over the goals of this post to help you get started. Node.jsAngular-CliAngular Workspace Angular Material Installing Node.js First step you need to do is to install\u2026","rel":"","context":"In &quot;Angular&quot;","block_context":{"text":"Angular","link":"https:\/\/www.mymiller.name\/wordpress\/category\/angular\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2019\/03\/geometry-1023846_640.jpg?fit=640%2C359&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2019\/03\/geometry-1023846_640.jpg?fit=640%2C359&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2019\/03\/geometry-1023846_640.jpg?fit=640%2C359&ssl=1&resize=525%2C300 1.5x"},"classes":[]},{"id":2847,"url":"https:\/\/www.mymiller.name\/wordpress\/angular\/angular-dymo-label-printer\/","url_meta":{"origin":2988,"position":2},"title":"Angular &#038; DYMO Label Printer","author":"Jeffery Miller","date":"September 14, 2020","format":false,"excerpt":"You can download the DYMO SDK. Now first thing you need to know is that at least at the time of this writing the the dymo.label.framework.js provided in the SDK does not work. Find the Internet Shortcut under the DYMO Label Framework > Samples > Javascript click on any of\u2026","rel":"","context":"In &quot;Angular&quot;","block_context":{"text":"Angular","link":"https:\/\/www.mymiller.name\/wordpress\/category\/angular\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2020\/09\/geometry-1023846_640.jpg?fit=640%2C359&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2020\/09\/geometry-1023846_640.jpg?fit=640%2C359&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2020\/09\/geometry-1023846_640.jpg?fit=640%2C359&ssl=1&resize=525%2C300 1.5x"},"classes":[]},{"id":3029,"url":"https:\/\/www.mymiller.name\/wordpress\/angular\/angular-material-loading-spinner\/","url_meta":{"origin":2988,"position":3},"title":"Angular Material Loading Spinner","author":"Jeffery Miller","date":"May 3, 2021","format":false,"excerpt":"Just about every project I need to have at least one loading spinner to indicate to the user that data is being loaded and to wait. My recent project I found that to be no exception. I wanted to come up with something that I thought was a little nicer\u2026","rel":"","context":"In &quot;Angular&quot;","block_context":{"text":"Angular","link":"https:\/\/www.mymiller.name\/wordpress\/category\/angular\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":3022,"url":"https:\/\/www.mymiller.name\/wordpress\/angular\/page-component-for-mobile-desktop\/","url_meta":{"origin":2988,"position":4},"title":"Page Component for Mobile\/Desktop","author":"Jeffery Miller","date":"April 26, 2021","format":false,"excerpt":"I was recently building a set of pages, that I needed to be able to switch what was displayed based on whether I was on a Desktop or Mobile device. On a Mobile device I would change the layout of tables or limit certain features in order to provide a\u2026","rel":"","context":"In &quot;Angular&quot;","block_context":{"text":"Angular","link":"https:\/\/www.mymiller.name\/wordpress\/category\/angular\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2021\/04\/website-1597382_640.png?fit=640%2C558&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2021\/04\/website-1597382_640.png?fit=640%2C558&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2021\/04\/website-1597382_640.png?fit=640%2C558&ssl=1&resize=525%2C300 1.5x"},"classes":[]},{"id":3811,"url":"https:\/\/www.mymiller.name\/wordpress\/angular\/streamline-your-workflow-generate-angular-services-from-spring-boot-rest-apis-with-gradle\/","url_meta":{"origin":2988,"position":5},"title":"Streamline Your Workflow: Generate Angular Services from Spring Boot REST APIs with Gradle","author":"Jeffery Miller","date":"February 24, 2025","format":false,"excerpt":"Integrating your Angular frontend with a Spring Boot backend can be a breeze if you automate the process of creating your Angular services. This post will show you how to leverage Gradle, OpenAPI (Swagger), and the OpenAPI Generator to generate type-safe Angular TypeScript services directly from your Spring Boot REST\u2026","rel":"","context":"In &quot;Angular&quot;","block_context":{"text":"Angular","link":"https:\/\/www.mymiller.name\/wordpress\/category\/angular\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/immune-defense-1359197_1280-jpg.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/immune-defense-1359197_1280-jpg.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/immune-defense-1359197_1280-jpg.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/immune-defense-1359197_1280-jpg.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/immune-defense-1359197_1280-jpg.avif 3x"},"classes":[]}],"jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/2988","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/comments?post=2988"}],"version-history":[{"count":2,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/2988\/revisions"}],"predecessor-version":[{"id":2994,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/2988\/revisions\/2994"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media\/2989"}],"wp:attachment":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media?parent=2988"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/categories?post=2988"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/tags?post=2988"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/series?post=2988"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}