<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ilya Radchenko</title>
    <description>The latest articles on DEV Community by Ilya Radchenko (@knownasilya).</description>
    <link>https://dev.to/knownasilya</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F84068%2Fa84baa54-5057-44d1-96dc-57d648ba8611.jpeg</url>
      <title>DEV Community: Ilya Radchenko</title>
      <link>https://dev.to/knownasilya</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/knownasilya"/>
    <language>en</language>
    <item>
      <title>6 Tips For Transitioning To Ember CSS Modules</title>
      <dc:creator>Ilya Radchenko</dc:creator>
      <pubDate>Fri, 10 Jan 2020 18:44:32 +0000</pubDate>
      <link>https://dev.to/knownasilya/6-tips-for-transitioning-to-ember-css-modules-2fep</link>
      <guid>https://dev.to/knownasilya/6-tips-for-transitioning-to-ember-css-modules-2fep</guid>
      <description>&lt;p&gt;A few tips as you transition your SASS, LESS, PostCSS or plain CSS to using CSS Modules, and specifically for Ember (not sure what the differences are).&lt;/p&gt;

&lt;h2&gt;
  
  
  Use &lt;code&gt;local-class&lt;/code&gt; Instead of &lt;code&gt;class&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;This is Ember only, and is just a requirement at the moment. This attribute is used to convert the generated classes and insert them into your template.If you pierce component styles (see next section), you should leave your old &lt;code&gt;class&lt;/code&gt; until you migrate away.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add Classes to Components Used In Templates
&lt;/h2&gt;

&lt;p&gt;CSS Modules don't let you style inside of components you use in your template, so you need to add a class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;User local-class="user" /&amp;gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Is required to target that component, otherwise you'd have to use &lt;code&gt;:global&lt;/code&gt;, which should be used sparingly. If you need to expose deeper classes, then it's recommended to add arguments, like &lt;code&gt;@roleClass&lt;/code&gt; and using the helper:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;User local-class="user" @roleClass={{local-class "role"}} /&amp;gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Use &lt;code&gt;:global&lt;/code&gt; Sparingly
&lt;/h2&gt;

&lt;p&gt;It's alright to use &lt;code&gt;:global&lt;/code&gt; if you do lots of component piercing and are migrating, but I recommend setting up stylelint and using the &lt;a href="https://stylelint.io/user-guide/rules/selector-pseudo-class-no-unknown"&gt;selector-pseudo-class-no-unknown&lt;/a&gt; rule, so you can catch missed globals when you go to refactor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
  rules: {
    "selector-pseudo-class-no-unknown": [
      true,
      {
        ignorePseudoClasses: ["global"],
      },
    ],
  },
};

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Wrap IDs in :global
&lt;/h2&gt;

&lt;p&gt;IDs get transformed, not sure why, so use &lt;code&gt;:global(#my-id) {}&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Refactor Away From Component CSS Parent Selector
&lt;/h2&gt;

&lt;p&gt;The following is not supported to target the default element (in classic components, or the route namespace):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;amp; {
  display: flex;
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You need to wrap that template in a new class, like &lt;code&gt;.page&lt;/code&gt;. This is especially true if you are transitioning to Glimmer components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't Use Element Selectors In The Top-Level
&lt;/h2&gt;

&lt;p&gt;You must include selectors like &lt;code&gt;h1, a, p&lt;/code&gt; inside of a class in your style file, otherwise those will apply to your whole app.This is because the style file doesn't get its own namespace, only the classes (and IDs) inside the file are renamed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Works Well With TailwindCSS
&lt;/h2&gt;

&lt;p&gt;In the past I've used Tailwind and have wondered about the case where you need to define your own components, it seemed like back to the same old CSS with it's normal limitations. CSS Modules enter stage right, and it's a great combination of using a subset of CSS and for the last 10% you dip into CSS Modules which live right next to your components.&lt;/p&gt;

&lt;p&gt;I've also been working on &lt;a href="https://subsetcss.netlify.app"&gt;SubsetCSS&lt;/a&gt; as a side project and it helps with keeping the same subset of CSS that Tailwind uses, so you can keep consistent styles across your whole codebase.&lt;/p&gt;

&lt;p&gt;Repost of &lt;a href="https://ilyaradchenko.com/6-tips-for-transitioning-to-ember-css-modules"&gt;https://ilyaradchenko.com/6-tips-for-transitioning-to-ember-css-modules&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ember</category>
      <category>cssmodules</category>
    </item>
    <item>
      <title>When Components Aren't Enough</title>
      <dc:creator>Ilya Radchenko</dc:creator>
      <pubDate>Wed, 08 Jan 2020 04:20:48 +0000</pubDate>
      <link>https://dev.to/knownasilya/when-components-aren-t-enough-1b30</link>
      <guid>https://dev.to/knownasilya/when-components-aren-t-enough-1b30</guid>
      <description>&lt;p&gt;Sometimes components are too high-level, and you need to get at a specific DOM element, either for &lt;code&gt;scrollTo&lt;/code&gt; or &lt;code&gt;focus&lt;/code&gt;, in these situations Ember provides a lower-level primitive called an element-modifier. To get started with element modifiers you can check out existing modifiers at &lt;a href="https://emberobserver.com/categories/modifiers"&gt;EmberObserver&lt;/a&gt; or create your own using the &lt;code&gt;ember-modifier&lt;/code&gt; &lt;a href="https://github.com/ember-modifier/ember-modifier"&gt;library&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some Examples
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight handlebars"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;autofocus&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Which will focus the first non-disabled input that it finds (from &lt;a href="https://github.com/qonto/ember-autofocus-modifier"&gt;ember-autofocus-modifier&lt;/a&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight handlebars"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;scroll-to&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Some content here
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Which will scroll to the element once it's in the DOM, and is super easy to implement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// /app/modifiers/scroll-to.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ember-modifier&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;modifier&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollIntoView&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;behavior&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;smooth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There is also the &lt;code&gt;ref&lt;/code&gt; modifier from &lt;a href="https://www.npmjs.com/package/ember-ref-modifier"&gt;ember-ref-modifier&lt;/a&gt; which gives you access to the element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight handlebars"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;ref&lt;/span&gt; &lt;span class="bp"&gt;this&lt;/span&gt; &lt;span class="s2"&gt;"button"&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt; &lt;span class="na"&gt;data-name=&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Click me baby, one more time!
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt; &amp;gt;&amp;gt; "foo"

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Along with &lt;code&gt;{{on-click-outside}}&lt;/code&gt; from &lt;a href="https://github.com/zeppelin/ember-click-outside"&gt;ember-click-outside&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight handlebars"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;on-click-outside&lt;/span&gt; &lt;span class="na"&gt;@close&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Your HTML...
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Why Are Element Modifiers Useful?
&lt;/h2&gt;

&lt;p&gt;Mainly because you can do things like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight handlebars"&gt;&lt;code&gt;&lt;span class="k"&gt;{{#if&lt;/span&gt; &lt;span class="nv"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;isEditorVisible&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"wysiwig-editor"&lt;/span&gt;
    &lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;did-insert&lt;/span&gt; &lt;span class="nv"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;setupEditor&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;
    &lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;will-destroy&lt;/span&gt; &lt;span class="nv"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;teardownEditor&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;{{/if}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Which handles the setup and teardown of the element, so if &lt;code&gt;isEditorVisible&lt;/code&gt; turns &lt;code&gt;false&lt;/code&gt; the editor initialized on our element will be properly cleaned up. This is important because the new Glimmer Components allow multiple top-level elements without any kind of fragment syntax.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: I'm using &lt;a href="https://github.com/emberjs/ember-render-modifiers"&gt;ember-render-modifiers&lt;/a&gt; in the above example. But you could create a modifier to encapsulate both the setup and teardown so reusability is easier.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
    </item>
    <item>
      <title>One Reason Why You Should Be Using URLs</title>
      <dc:creator>Ilya Radchenko</dc:creator>
      <pubDate>Fri, 03 Jan 2020 03:40:30 +0000</pubDate>
      <link>https://dev.to/knownasilya/one-reason-why-you-should-be-using-urls-18je</link>
      <guid>https://dev.to/knownasilya/one-reason-why-you-should-be-using-urls-18je</guid>
      <description>&lt;p&gt;One of the reasons that &lt;a href="https://emberjs.com"&gt;Ember.js&lt;/a&gt; is so powerful of a framework is because of its Router, and ultimately its bet on the web and the fact that the URL is important. With Ember's router, the URL becomes a nested state-machine for your app, which is one of the reasons you should be using URLs in your app whenever you can. Let me explain a bit.&lt;/p&gt;

&lt;p&gt;I'm just learning about state-machines, and from what I can tell one of the basics is that in the most simplest of state-machines, you represent a single state that can happen at one time. So for example, &lt;code&gt;fetching&lt;/code&gt; or &lt;code&gt;errored&lt;/code&gt; for an AJAX request, you cannot be in both states. Ember.js gives you these two for free in the router, the &lt;a href="https://guides.emberjs.com/release/routing/loading-and-error-substates/#toc_loading-substates"&gt;&lt;code&gt;loading&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://guides.emberjs.com/release/routing/loading-and-error-substates/#toc_error-substates"&gt;&lt;code&gt;errored&lt;/code&gt;&lt;/a&gt; routes (or substates as the guides call them).&lt;/p&gt;

&lt;p&gt;The way that Ember has routes and UI setup promotes these exclusive states in the UI, because nested routes map to nested UI. So if you have a wizard UI for an onboarding kind of experience, you can model each step of that onboarding flow as a nested route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;this.route('onboarding', function () {
  // 'index' is predefined and is step 0
  this.route('step1');
  this.route('step2');
  this.route('step3');
  // 'loading' is predefined
  // 'errored' is predefined
});

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see, if you visit &lt;code&gt;onboarding&lt;/code&gt; you will land on the &lt;code&gt;index&lt;/code&gt; route, which can be step 0 or can redirect you to the correct step. This is the initial state of our onboarding state-machine. If the &lt;code&gt;index&lt;/code&gt; route loads something, it will transition to &lt;code&gt;loading&lt;/code&gt; before rendering. So you can only be in one of the substates of the &lt;code&gt;onboarding&lt;/code&gt; route.&lt;/p&gt;

&lt;p&gt;You can now transition from &lt;code&gt;index&lt;/code&gt; to another sibling route using &lt;code&gt;transitionTo&lt;/code&gt; on the &lt;a href="https://api.emberjs.com/ember/release/classes/RouterService"&gt;&lt;code&gt;router&lt;/code&gt; service&lt;/a&gt; or on routes (&lt;code&gt;transitionToRoute&lt;/code&gt; in a controller). Something like &lt;code&gt;this.router.transitionTo('onboarding.step1')&lt;/code&gt;. Once again &lt;code&gt;loading&lt;/code&gt; and maybe &lt;code&gt;errored&lt;/code&gt; will be entered during/after the &lt;code&gt;model&lt;/code&gt; loading phase. Using this structure to define nested UI, since the child routes are nested in whatever UI is defined in the &lt;code&gt;onboarding&lt;/code&gt; template, allows you to define exclusive states and prevents subtle bugs that might creep up if you decided to handle these steps using &lt;code&gt;{{#if (eq this.step 'step1')}}&lt;/code&gt; syntax, especially if you have multiple if statements for the same state for different pieces of UI, it makes it hard to reason about and allows your app to be in unknown states you didn't intent.&lt;/p&gt;

&lt;p&gt;So in closing, the URL is important, because it drives nested UI in a state-machine fashion which keeps your app easier to understand, read, and prevents bugs in many cases.&lt;/p&gt;

&lt;p&gt;If you want to read more about routing, check out my post about &lt;a href="https://ilyaradchenko.com/using-nested-routes-in-ember"&gt;Using Nested Routes In Ember&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ember</category>
      <category>routing</category>
    </item>
    <item>
      <title>Ember's Nested Routes and URLs Explored</title>
      <dc:creator>Ilya Radchenko</dc:creator>
      <pubDate>Thu, 05 Dec 2019 22:14:07 +0000</pubDate>
      <link>https://dev.to/knownasilya/ember-s-nested-routes-and-urls-explored-19l8</link>
      <guid>https://dev.to/knownasilya/ember-s-nested-routes-and-urls-explored-19l8</guid>
      <description>&lt;p&gt;Ember's router is powerful and a bit unique, in that it has a nested structure for the routes which build up the URL a user would see in the browser.Given it's power, it is easy to be unsure about how to structure your routes, especially in scenarios where you have parent-child UI patterns or CRUD like resources.&lt;/p&gt;

&lt;p&gt;One of the patterns that I've learned is not using extra nesting when want to build out a multi-part URL structure, like &lt;code&gt;/users/1234&lt;/code&gt;, which seems like it should be nested, but generally a single level is enough. I'd structure it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;this.route('user', { path: '/users/:userId' });

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This puts your user "view" route at the &lt;code&gt;app/pods/user&lt;/code&gt; directory (my examples will use PODS, since they are sane for routes).The following is generally not the way I'd write my router map, even though it creates the same URL pattern.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;this.route('users', function () {
this.route('user', { path: ':userId' });
});

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Unless you are showing the list of users at the same time as the selected user, which I think is a rare pattern, this is probably not the way your route should work.The reason I wouldn't do this is because it adds unnecessary mental overhead between the list and a selected item from the list.With my preferred pattern, if I wanted a list route, it would be a sibling to the resources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;this.route('users');
this.route('user', { path: '/users/:userId' });

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And the folder structure is sane as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app
pods
  users
  user

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Since the two usually don't share any common UI, the common UI will probably be one route up or at the &lt;code&gt;application&lt;/code&gt; route.Well that's it! Let me know if this is how you do it or if you completely disagree.&lt;/p&gt;

</description>
      <category>ember</category>
      <category>routing</category>
    </item>
  </channel>
</rss>
