<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>javascript on tkainrad</title>
    <link>https://tkainrad.dev/tags/javascript/</link>
    <description>Recent content in javascript on tkainrad</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Thu, 08 Apr 2021 00:00:00 +0000</lastBuildDate>
    
        <atom:link href="https://tkainrad.dev/tags/javascript/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Why Keyboard Shortcuts don&#39;t work on non-US Layouts and how Devs could fix it</title>
      <link>https://tkainrad.dev/posts/why-keyboard-shortcuts-dont-work-on-non-us-keyboard-layouts-and-how-to-fix-it/</link>
      <pubDate>Thu, 08 Apr 2021 00:00:00 +0000</pubDate>
      
      <guid>https://tkainrad.dev/posts/why-keyboard-shortcuts-dont-work-on-non-us-keyboard-layouts-and-how-to-fix-it/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;During the past 15 months, I have been thinking a lot about keyboard shortcuts and about how different applications handle them. I shouldn&amp;rsquo;t complain; I knew what I was getting into when I started to build &lt;a href=&#34;https://keycombiner.com/&#34;&gt;KeyCombiner&lt;/a&gt;, an app for learning and looking up shortcuts and text snippets. Still, I didn&amp;rsquo;t quite know how much of a mess keyboard shortcut handling on the web is.&lt;/p&gt;
&lt;p&gt;Do you use an international keyboard layout? Then you already know what I am talking about. You probably have had some issues typing keyboard shortcuts such as &lt;kbd&gt;alt&lt;/kbd&gt;+&lt;kbd&gt;/&lt;/kbd&gt;, or &lt;kbd&gt;cmd&lt;/kbd&gt;+&lt;kbd&gt;[&lt;/kbd&gt;. This post will help you to understand why this annoyance exists. However, the people who should most urgently read this post are web developers. Are you a web developer? Great! I will explain how you are currently letting down non-US users and how you can get us out of this mess.&lt;/p&gt;

&lt;div class=&#34;notices info&#34;&gt;
    &lt;p&gt;I will focus on web applications. The behavior on desktop apps is often different. However, with the rise of Electron apps, web technologies are ever-present on the desktop as well. So, the arguments in this article probably apply to half of your installed apps as well.&lt;/p&gt;

&lt;/div&gt;
&lt;h1 id=&#34;examples-of-broken-apps&#34;&gt;Examples of Broken Apps&lt;/h1&gt;
&lt;p&gt;The problem I am talking about is so incredibly omnipresent that most international users are just used to the fact that they cannot type a good portion of a given web application&amp;rsquo;s keyboard shortcuts on their keyboards. However, web applications are becoming increasingly complex, and they are rapidly replacing desktop applications, making this problem bigger by the day.&lt;/p&gt;
&lt;p&gt;This is most annoying when the most important keyboard shortcuts are inaccessible. A very common shortcut is &lt;kbd&gt;/&lt;/kbd&gt; for accessing search functionality. Unfortunately, there is no &lt;kbd&gt;/&lt;/kbd&gt;-key on most international layouts. Adding modifiers to produce this key with your layout rarely helps. For example, on my German layout, &lt;kbd&gt;/&lt;/kbd&gt; is produced via &lt;kbd&gt;Shift&lt;/kbd&gt;+&lt;kbd&gt;7&lt;/kbd&gt;. Most web applications will ignore this.
Similarly painful is when Electron apps use &lt;kbd&gt;[&lt;/kbd&gt; and &lt;kbd&gt;]&lt;/kbd&gt; for navigating backwards and forwards.&lt;/p&gt;
&lt;p&gt;If you use a US layout, you might be surprised to hear about these problems. But rest assured, they are not new and I am not the only one who is affected.
We are at a point where it is easy to find users complaining about this for almost any popular web application.&lt;/p&gt;
&lt;p&gt;An interesting example are Google&amp;rsquo;s apps. For some reason, Google manages to handle international layouts correctly in Gmail, but fails to do so in any of its other applications. The web is full of complaints, e.g. for &lt;a href=&#34;https://webapps.stackexchange.com/questions/116405/google-spreadsheet-equivalent-of-excels-ctrlsemicolon-on-international-keyboar&#34;&gt;Google Sheets&lt;/a&gt;, &lt;a href=&#34;https://webapps.stackexchange.com/questions/114185/google-drive-keyboard-shortcuts-not-working-with-non-us-keyboard&#34;&gt;Google Drive&lt;/a&gt;, and &lt;a href=&#34;https://superuser.com/questions/217082/why-dont-the-google-docs-ctrl-alt-shortcuts-work&#34;&gt;Google Docs&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&#34;notices info&#34;&gt;
    &lt;p&gt;Update: International Layouts now work in Google Chat. Interestingly, the fix was applied shortly after this article &lt;a href=&#34;https://tkainrad.dev/posts/why-keyboard-shortcuts-dont-work-on-non-us-keyboard-layouts-and-how-to-fix-it/&#34;&gt;reached the front page of Hacker News&lt;/a&gt;. I am not saying that these events are correlated, but it is a nice thought.&lt;br&gt;
Unfortunately, the problem persists for other Google Apps, such as GDrive.&lt;/p&gt;

&lt;/div&gt;
&lt;p&gt;Another, almost funny examply is Figma, the popular web-based vector-graphics editor. So many people &lt;a href=&#34;https://spectrum.chat/figma/general/shortcuts-on-german-keyboard~972dac03-c1c6-4dc0-9233-020b2bfac038&#34;&gt;complained&lt;/a&gt; that there is now a &lt;a href=&#34;https://www.figma.com/proto/q2OVHiUu6hdDiOZLzDmUL9/Shortcuts-(International)?scaling=contain&amp;amp;node-id=10%3A234&#34;&gt;dedicated site with workarounds for different layouts&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://forum.asana.com/t/support-for-keyboard-shortcuts-with-international-layouts/15430&#34;&gt;This complaint in the Asana forums&lt;/a&gt; is funny too. They made some specific adjustments for some layouts, only to give up in the end and say that they will still not support more exotic layouts.&lt;/p&gt;
&lt;p&gt;There are also plenty of complaints for Notion, see &lt;a href=&#34;https://twitter.com/NotionHQ/status/997602351740432384&#34;&gt;here&lt;/a&gt; or &lt;a href=&#34;https://www.reddit.com/r/Notion/comments/fi6cis/german_qwertz_keyboard_hack_to_remap/&#34;&gt;here&lt;/a&gt;. The competition doesn&amp;rsquo;t do much better, though, &lt;a href=&#34;https://github.com/Roam-Research/issues/issues/131&#34;&gt;here is an open issue for Roam Research&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&#34;notices tip&#34;&gt;
    &lt;p&gt;Finding all these applications with broken shortcut handling was very easy. I used &lt;a href=&#34;https://keycombiner.com/collecting/collections/public/search/?description=&amp;amp;keys=%2F&amp;amp;mac_keys=&amp;amp;submit=Search&#34;&gt;KeyCombiner&amp;rsquo;s shortcut search to find all applications that use the US &lt;kbd&gt;/&lt;/kbd&gt;-key in their shortcuts&lt;/a&gt;. Then I googled and found complaints for most of these apps. In the case of Notion and Google Drive/Docs/Sheets, I was already aware simply because I use these applications myself.&lt;/p&gt;

&lt;/div&gt;
&lt;p&gt;I want to be clear, broken keyboard shortcuts are not a law of nature. It is possible to implement web application shortcuts so that they can be typed with any layout. It shouldn&amp;rsquo;t be an excuse that even some of the most popular apps do not get it right.&lt;/p&gt;
&lt;h1 id=&#34;why-is-this-happening&#34;&gt;Why is this happening?&lt;/h1&gt;
&lt;p&gt;What baffles me is that the problem exists in apps used by millions of people every day, developed by gigantic corporations who pride themselves with having the best engineers in the world. Why is this baffling? Because the underlying technical issues are rather trivial!&lt;/p&gt;
&lt;p&gt;Web applications use JavaScript to process keyboard shortcuts. To do that, they listen to keyboard events that are emitted by your browser whenever your press a key. That&amp;rsquo;s where it gets a little messy. These keyboard events have several properties that can be used to identify which keys have been pressed. To make matters worse, three different events are associated with a single button press: &lt;code&gt;keydown&lt;/code&gt; &lt;code&gt;keypress&lt;/code&gt; &lt;code&gt;keyup&lt;/code&gt;. Most applications use a Javascript library that handles all these things for them, primarily &lt;a href=&#34;https://github.com/jaywcjlove/hotkeys&#34;&gt;HotKeys.js&lt;/a&gt; or &lt;a href=&#34;https://github.com/ccampbell/mousetrap&#34;&gt;Mousetrap&lt;/a&gt;. Let&amp;rsquo;s look at &lt;a href=&#34;https://github.com/jaywcjlove/hotkeys/blob/8b398e9c24c462f06e4d2acb47a5403295eaabcf/dist/hotkeys.js#L358&#34;&gt;what Hotkeys.js does&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;color:#069;font-weight:bold&#34;&gt;let&lt;/span&gt; key &lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt; event.keyCode &lt;span style=&#34;color:#555&#34;&gt;||&lt;/span&gt; event.which &lt;span style=&#34;color:#555&#34;&gt;||&lt;/span&gt; event.charCode;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It uses &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode&#34;&gt;&lt;code&gt;keyCode&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/which&#34;&gt;&lt;code&gt;which&lt;/code&gt;&lt;/a&gt;, or &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/charCode&#34;&gt;&lt;code&gt;charCode&lt;/code&gt;&lt;/a&gt; to find out which key was pressed. Why is this a problem? For starters, all three properties are deprecated. That isn&amp;rsquo;t even the main problem though. These event properties are simply not suited for finding out which character was pressed, at least when used with &lt;code&gt;keydown&lt;/code&gt; or &lt;code&gt;keyup&lt;/code&gt;. Still a vast majority of web applications use the &lt;code&gt;keydown&lt;/code&gt; evente with these properties.
It is very clearly documented that this should not be done and that it is not compatible across layouts, operating systems, and even browsers. To cite the MDN web docs:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Web developers shouldn&amp;rsquo;t use the keyCode attribute for printable characters when handling keydown and keyup events. As described above, the keyCode attribute is not useful for printable characters, especially those input with the Shift or Alt key pressed. When implementing a shortcut key handler, the keypress event is usually better.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Using Chrome on Linux with a german keyboard, my &lt;kbd&gt;#&lt;/kbd&gt; key will produce the required &lt;code&gt;keyCode&lt;/code&gt; for triggering &lt;kbd&gt;/&lt;/kbd&gt; shortcuts. However, this does not work on Firefox, and neither does it work on Chrome on macOS. With many browser and OS combinations, there is no way to trigger this shortcut on a german layout. The same goes for many other international keyboard layouts that do not have a dedicated &lt;kbd&gt;/&lt;/kbd&gt;-key.&lt;/p&gt;
&lt;p&gt;If you want to see which button presses produce which event properties, you can use this neat little web tool:
&lt;a href=&#34;https://w3c.github.io/uievents/tools/key-event-viewer.html&#34;&gt;https://w3c.github.io/uievents/tools/key-event-viewer.html&lt;/a&gt;&lt;br&gt;
Hint for developers: Switch your computer&amp;rsquo;s keyboard layout to something other than US to debug your application&amp;rsquo;s shortcut handling on different layouts.&lt;/p&gt;
&lt;p&gt;Using this event viewer, you will see that the &lt;code&gt;keypress&lt;/code&gt; event usually produces the correct code on any layout. Unfortunately, this event is deprecated as a whole and comes with its own problems. Still, the &lt;a href=&#34;https://github.com/ccampbell/mousetrap&#34;&gt;Mousetrap&lt;/a&gt; library can use the &lt;code&gt;keypress&lt;/code&gt; event with fairly good results on international layouts.&lt;/p&gt;
&lt;p&gt;As you can see, the situation is messy. However, developers are usually pretty good at dealing with complex problems. In the next section, I will point out some straightforward ways to do better than Google and other tech giants.&lt;/p&gt;
&lt;h1 id=&#34;how-you-can-do-better&#34;&gt;How you can do better&lt;/h1&gt;
&lt;p&gt;The good news is that this problem is easy to fix. Depending on your resources and the technical and semantical requirements of your application, there are a few things that you could do:&lt;/p&gt;
&lt;h2 id=&#34;simple-workarounds&#34;&gt;Simple Workarounds&lt;/h2&gt;
&lt;p&gt;If your web application does not have a huge amount of shortcuts, or if you don&amp;rsquo;t have the resources to spend a meaningful amount of engineering work on this problem, here are some trivial ways to work around the described issues.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do not use special characters for your keyboard shortcuts.&lt;/strong&gt;&lt;br&gt;
That&amp;rsquo;s all you would need to do to make 99% of your international users happy. If you want to go one step further, you can try to stay on the home row or choose otherwise easy-to-type characters. In case you have an existing application with shortcuts that cannot be changed because your American users already learned them, consider the suggestion below.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Provide Alternatives&lt;/strong&gt;&lt;br&gt;
If you really do need to use special characters, provide alternatives that can be typed on all keyboard layouts. Both HotKeys.js and Mousetrap support multiple triggers when creating your bindings.
For example if you have &lt;kbd&gt;/&lt;/kbd&gt; as you shortcut for focusing the search field because your US users are accustomed to this behavior, just add &lt;kbd&gt;alt&lt;/kbd&gt;+&lt;kbd&gt;s&lt;/kbd&gt; as an alternative for international users. Some US users might welcome this change as well, because &lt;kbd&gt;alt&lt;/kbd&gt;+&lt;kbd&gt;s&lt;/kbd&gt; can be typed with just the left hand while &lt;kbd&gt;/&lt;/kbd&gt; reqiures people to take their hand of the mouse.&lt;/p&gt;
&lt;h2 id=&#34;technical-fixes&#34;&gt;Technical Fixes&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Actually make the shortcuts work with any keyboard layout.&lt;/strong&gt;&lt;br&gt;
This means when the key combination is &lt;kbd&gt;alt&lt;/kbd&gt;+&lt;kbd&gt;/&lt;/kbd&gt;, the shortcut should be triggered when a german layout user presses &lt;kbd&gt;alt&lt;/kbd&gt;+&lt;kbd&gt;shift&lt;/kbd&gt;+&lt;kbd&gt;7&lt;/kbd&gt;. This is surprisingly easy with some of the popular shortcut processing libraries. With Mousetrap, all you need to do is listen to the &lt;code&gt;keypress&lt;/code&gt; events instead of &lt;code&gt;keydown&lt;/code&gt;. In the next section of this post, I will mention some applications that work this way.
Unfortunately, there is a minor downside to this approach. It can make some shortcuts tedious to type on some layouts, e.g. requiring two or three modifiers. It also has some potential for shortcut conflicts. &lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;/&lt;/kbd&gt; is suddenly the same as &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;shift&lt;/kbd&gt;+&lt;kbd&gt;7&lt;/kbd&gt;. You should be aware of that and not assign these things to two different bindings. The easiest way to avoid such conflicts is by staying away from the &lt;kbd&gt;Shift&lt;/kbd&gt; modifier when defining your bindings.&lt;/p&gt;
&lt;p&gt;If you want to go all the way, you could write your own shortcut processing code, and possibly make it into an open-source library. The current alternatives do not care too much about supporting different layouts.
There are a lot of things one could do to solve all the issues described in this article. For example, you could use the &lt;code&gt;key&lt;/code&gt; attribute, or even play around with the experimental &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/API/Keyboard/getLayoutMap&#34;&gt;&lt;code&gt;keyboard.getLayoutMap&lt;/code&gt; API&lt;/a&gt;. KeyCombiner uses this API to display its &lt;a href=&#34;https://tkainrad.dev/posts/visualize-collections-of-keyboard-shortcuts/&#34;&gt;on-screen virtual keyboards&lt;/a&gt; with the user&amp;rsquo;s layout.
Sometimes, I think about making such a library myself. KeyCombiner already uses a fork of Mousetrap that has been customized quite a bit. However, I already have a demanding full-time job and a large side-project, so I would be happy if you beat me to it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Allow users to change the default key bindings.&lt;/strong&gt;&lt;br&gt;
This way, users of international keyboard layouts, can change invalid bindings to something that works for them. As a bonus, you would make any shortcut enthusiast happy, and your marketing people could point out how all your sorry-ass competitors do not allow custom keyboard shortcuts.&lt;/p&gt;
&lt;p&gt;Interestingly, I am not aware of a single web application that lets you customize keyboard shortcuts, even though it wouldn&amp;rsquo;t be that difficult to implement, especially with modern SPAs that would have to pull the custom bindings from the database only once. You could store them in your database, pull them out when a user logs in, and pass them to your shortcut processing library.&lt;/p&gt;
&lt;h1 id=&#34;wall-of-fame&#34;&gt;Wall of Fame&lt;/h1&gt;
&lt;p&gt;Fortunately, some applications already do it right. Three apps that I am using where my german layout works flawlessly are Gmail, Linear, and Discourse.&lt;/p&gt;
&lt;h2 id=&#34;gmail&#34;&gt;Gmail&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s hard to believe that Gmail is created by the same company as Google Drive, Google Chat, and many other apps that do not handle shortcuts correctly on international layouts. The Gmail web interface works great on all layouts that I tested. On my german layout, I can even use &lt;kbd&gt;AltGr&lt;/kbd&gt;+&lt;kbd&gt;8&lt;/kbd&gt; to archive a conversation (&lt;kbd&gt;[&lt;/kbd&gt;). Similarly, search can be triggered via &lt;kbd&gt;shift&lt;/kbd&gt;+&lt;kbd&gt;7&lt;/kbd&gt; (&lt;kbd&gt;/&lt;/kbd&gt;). Note that this is &lt;strong&gt;the exact same shortcut that does not work in all the other Google apps&lt;/strong&gt;. So, if you work at Google, maybe ask your colleagues on the Gmail team for a little help.&lt;/p&gt;
&lt;h2 id=&#34;discourse&#34;&gt;Discourse&lt;/h2&gt;
&lt;p&gt;Discourse is a great example because it is an open-source application, meaning that you can go to their &lt;a href=&#34;https://github.com/discourse/discourse&#34;&gt;GitHub repository&lt;/a&gt; and see &lt;a href=&#34;https://github.com/discourse/discourse/blob/f0b2e77abb932f118878951fa75911db2d3a3013/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js&#34;&gt;how they are doing it&lt;/a&gt;. The answer is very simple: They use the Mousetrap library with &lt;code&gt;keypress&lt;/code&gt;. As explained above, &lt;code&gt;keyCode&lt;/code&gt;/&lt;code&gt;which&lt;/code&gt;/&lt;code&gt;charCode&lt;/code&gt; will contain the right code even on international layouts when used with &lt;code&gt;keypress&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;linear&#34;&gt;Linear&lt;/h2&gt;
&lt;p&gt;Linear is a relatively new and increasingly popular issue tracking software. It takes pride in having a &lt;em&gt;keyboard first design&lt;/em&gt;, and being &lt;em&gt;optimized for efficiency with extensive keyboard shortcuts&lt;/em&gt;. Their recent success story and my personal experience suggest that they deliver on this promise. Of course, many other web apps have a lot of keyboard shortcuts, too. However, with Linear, they actually work.&lt;/p&gt;

&lt;div class=&#34;notices question&#34;&gt;
    &lt;p&gt;Do you know other applications that work with all keyboard layouts? Please let me know in the comments below, and I will add them here.&lt;/p&gt;

&lt;/div&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Next time you use an app that dangles its keyboard shortcut definitions in front of you, just so you can find out that they don&amp;rsquo;t work with your layout, please remember this post. You will know that there are ways to fix this.&lt;/p&gt;
&lt;p&gt;If you are in the mood, you can write a nice message to the developers, explaining how they are probably misusing the &lt;code&gt;keydown&lt;/code&gt; event and its &lt;code&gt;keyCode&lt;/code&gt; property. We shouldn&amp;rsquo;t have to live like this.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Using VueJS alongside Django</title>
      <link>https://tkainrad.dev/posts/use-vuejs-with-django/</link>
      <pubDate>Tue, 14 Apr 2020 00:00:00 +0000</pubDate>
      
      <guid>https://tkainrad.dev/posts/use-vuejs-with-django/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;I am currently working on a very exciting project. The whole thing is quite challenging because the project&amp;rsquo;s scope is significant, and I am doing it alone in my spare time while working full time. So I have to be very efficient. Fortunately, I am using Django with its &lt;a href=&#34;https://docs.djangoproject.com/en/3.0/ref/contrib/&#34;&gt;&lt;em&gt;batteries-included&lt;/em&gt;&lt;/a&gt; approach.&lt;/p&gt;

&lt;div class=&#34;notices info&#34;&gt;
    &lt;p&gt;The mentioned project is now in Open Beta! You can have a look at &lt;a href=&#34;https://keycombiner.com&#34;&gt;https://keycombiner.com&lt;/a&gt;.&lt;br&gt;
It is a web application to organize the keyboard shortcuts you use, get better at using them, and to learn new ones.&lt;/p&gt;

&lt;/div&gt;
&lt;p&gt;I use all kinds of Django features that speed up my development, and I wouldn&amp;rsquo;t want to miss its template engine. Therefore, using Django only in the backend and building a JavaScript SPA for the frontend is not an option for me.&lt;br&gt;
However, even the most avid backend developer has to admit that some things warrant a client-side implementation. Small user actions should not require page reloads. Also, some parts of the web application I am building require rather sophisticated user interaction.&lt;/p&gt;
&lt;p&gt;Traditionally, one would mix Django with some jQuery to achieve the desired behavior. But there are newer JavaScript technologies now: &lt;a href=&#34;https://vuejs.org/&#34;&gt;React&lt;/a&gt; and &lt;a href=&#34;https://vuejs.org/&#34;&gt;Vue&lt;/a&gt;.&lt;br&gt;
Since our goal is to find a framework that we can use alongside Django without rethinking everything, we will go for Vue as the more lightweight alternative.
In this post, I will show that you can start to use Vue alongside Django&amp;rsquo;s template language with minimal effort.&lt;/p&gt;
&lt;h1 id=&#34;installation-and-setup&#34;&gt;Installation and Setup&lt;/h1&gt;
&lt;p&gt;One of the reasons to use Vue is its excellent &lt;a href=&#34;https://vuejs.org/v2/guide/&#34;&gt;documentation&lt;/a&gt;. It includes many examples, has a decent search, and a reasonably clear table of contents.&lt;/p&gt;
&lt;p&gt;This post aims to show that you can start to use Vue with your Django projects immediately without any sophisticated setup that will take hours to complete. Therefore, we will use the simplest method to use Vue.js: Including it via a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;&amp;lt;!-- development version, includes helpful console warnings --&amp;gt;&lt;/span&gt;
&amp;lt;&lt;span style=&#34;color:#309;font-weight:bold&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#309&#34;&gt;src&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;https://cdn.jsdelivr.net/npm/vue/dist/vue.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#309;font-weight:bold&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That is it, we are now ready to create our first Vue.js instance:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&amp;lt;&lt;span style=&#34;color:#309;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#309&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;app&amp;#34;&lt;/span&gt;&amp;gt;
  {{ message }}
&amp;lt;/&lt;span style=&#34;color:#309;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;display:block;width:100%;background-color:#d8dada&#34;&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;color:#069;font-weight:bold&#34;&gt;var&lt;/span&gt; app &lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#069;font-weight:bold&#34;&gt;new&lt;/span&gt; Vue({
&lt;span style=&#34;display:block;width:100%;background-color:#d8dada&#34;&gt;  delimiters&lt;span style=&#34;color:#555&#34;&gt;:&lt;/span&gt; [&lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;[[&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;]]&amp;#34;&lt;/span&gt;],
&lt;/span&gt;  el&lt;span style=&#34;color:#555&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;#app&amp;#39;&lt;/span&gt;,
  data&lt;span style=&#34;color:#555&#34;&gt;:&lt;/span&gt; {
    message&lt;span style=&#34;color:#555&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;Hello Vue!&amp;#39;&lt;/span&gt;
  }
})
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This example is taken from the official Getting Started Guide. However, there is one addition. Per default, Django and Vue use the same template tags. Hence, we need to set the Vue delimiters explicitly to avoid conflicts with Django&amp;rsquo;s template engine.&lt;/p&gt;
&lt;h1 id=&#34;access-django-data-from-vue&#34;&gt;Access Django Data from Vue&lt;/h1&gt;
&lt;p&gt;The simplest way to do so is the &lt;a href=&#34;https://docs.djangoproject.com/en/3.0/ref/templates/builtins/#json-script&#34;&gt;built-in Django jscon_script filter&lt;/a&gt;.
This way you can immediately start using your Django models as data for your Vue instances.&lt;/p&gt;
&lt;p&gt;In HTML:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;{{ django_template_variable|json_script:&amp;#34;djangoData&amp;#34; }}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, in JavaScript, we load this data into a variable:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;color:#069;font-weight:bold&#34;&gt;let&lt;/span&gt; jsVariable &lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt; JSON.parse(&lt;span style=&#34;color:#366&#34;&gt;document&lt;/span&gt;.getElementById(&lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;djangoData&amp;#39;&lt;/span&gt;).textContent);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And it is ready to use with Vue:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;color:#069;font-weight:bold&#34;&gt;new&lt;/span&gt; Vue({
  delimiters&lt;span style=&#34;color:#555&#34;&gt;:&lt;/span&gt; [&lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;[[&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;]]&amp;#34;&lt;/span&gt;],
  el&lt;span style=&#34;color:#555&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;#app&amp;#39;&lt;/span&gt;,
  data&lt;span style=&#34;color:#555&#34;&gt;:&lt;/span&gt; jsVariable
})
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;make-async-backend-requests&#34;&gt;Make async Backend Requests&lt;/h1&gt;
&lt;p&gt;One of the most frequent tasks of a Vue frontend is to make requests to a backend server application. With a full-stack Django application, we don&amp;rsquo;t have to do this for every user interaction. In some cases, a full page reload might be perfectly fine, and Django&amp;rsquo;s templating system provides all kinds of advantages. But to enhance user experience and to reap the full benefits of using Vue, we may still want to make backend requests in some places.&lt;/p&gt;
&lt;p&gt;Vue itself cannot handle requests. In this post, I will use &lt;a href=&#34;https://github.com/axios/axios&#34;&gt;axios&lt;/a&gt;, because it is also recommended in the official Vue Docs. Other alternatives are perfectly fine too.&lt;/p&gt;
&lt;p&gt;To pass Django&amp;rsquo;s CSRF protection mechanism, axios needs to include the respective cookie in its requests. The easiest way to accomplish this is to set global axios defaults:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;axios.defaults.xsrfCookieName &lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;csrftoken&amp;#39;&lt;/span&gt;;
axios.defaults.xsrfHeaderName &lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;X-CSRFTOKEN&amp;#34;&lt;/span&gt;;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Alternatively, we could also create an axios instance with the required settings:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;color:#069;font-weight:bold&#34;&gt;var&lt;/span&gt; instance &lt;span style=&#34;color:#555&#34;&gt;=&lt;/span&gt; axios.create({
    xsrfCookieName&lt;span style=&#34;color:#555&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;csrftoken&amp;#39;&lt;/span&gt;,
    xsrfHeaderName&lt;span style=&#34;color:#555&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#c30&#34;&gt;&amp;#34;X-CSRFTOKEN&amp;#34;&lt;/span&gt;,
});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&#34;notices info&#34;&gt;
    &lt;p&gt;Your Django template needs to contain the tag &lt;code&gt;{% csrf_token %}&lt;/code&gt; or, alternatively, the respective view must use the decorator &lt;a href=&#34;https://docs.djangoproject.com/en/3.0/ref/csrf/#django.views.decorators.csrf.ensure_csrf_cookie&#34;&gt;&lt;code&gt;ensure_csrf_cookie()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;/div&gt;
&lt;p&gt;The rest of Django&amp;rsquo;s default session backend for authentication will work out of the box, meaning that you can annotate your backend services with things like &lt;code&gt;loginRequired&lt;/code&gt; and it will just work.
To make the request, we can use axios as usual:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f3f3;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;axios.post(&lt;span style=&#34;color:#c30&#34;&gt;&amp;#39;/django/backend/endpoint&amp;#39;&lt;/span&gt;, {
    data&lt;span style=&#34;color:#555&#34;&gt;:&lt;/span&gt; jsVariable 
})
    .then(&lt;span style=&#34;color:#069;font-weight:bold&#34;&gt;function&lt;/span&gt; (response) {
        &lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;// handle response
&lt;/span&gt;&lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;&lt;/span&gt;    })
    .&lt;span style=&#34;color:#069;font-weight:bold&#34;&gt;catch&lt;/span&gt;(&lt;span style=&#34;color:#069;font-weight:bold&#34;&gt;function&lt;/span&gt; (error) {
        &lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;// handle error
&lt;/span&gt;&lt;span style=&#34;color:#09f;font-style:italic&#34;&gt;&lt;/span&gt;    });
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This call can be done within a Vue instance&amp;rsquo;s &lt;code&gt;mounted&lt;/code&gt; hook or any other place where you can put JavaScript code.&lt;/p&gt;

&lt;div class=&#34;notices warning&#34;&gt;
    &lt;p&gt;If you activated &lt;code&gt;CSRF_USE_SESSIONS&lt;/code&gt; or &lt;code&gt;CSRF_COOKIE_HTTPONLY&lt;/code&gt; in your Django settings, you need to read the CSRF token from the DOM. For more details, see &lt;a href=&#34;https://docs.djangoproject.com/en/3.0/ref/csrf/#acquiring-the-token-if-csrf-use-sessions-or-csrf-cookie-httponly-is-true&#34;&gt;the official Django docs&lt;/a&gt;.&lt;/p&gt;

&lt;/div&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;When you google for &lt;em&gt;Django + Vue&lt;/em&gt;, most results will be focused on using Django for your backend and Vue for a separate frontend project. Having two independent projects increases complexity, and you lose access to Django&amp;rsquo;s template system, which is a very powerful timesaver. On the other hand, access to a frontend framework such as Vue can do wonders for web applications that go beyond CRUD functionality.&lt;/p&gt;
&lt;p&gt;Fortunately, we do not need to decide between the two. This guide shows that you can have the cake and eat it too!&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>