<?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: Eli H. Schei</title>
    <description>The latest articles on DEV Community by Eli H. Schei (@elischei).</description>
    <link>https://dev.to/elischei</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%2F578615%2F23911f4c-6967-4eb0-8d59-7b8ccec18a4e.jpg</url>
      <title>DEV Community: Eli H. Schei</title>
      <link>https://dev.to/elischei</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/elischei"/>
    <language>en</language>
    <item>
      <title>How to upgrade your SPfx project to the latest version, and how to fix/avoid common issues</title>
      <dc:creator>Eli H. Schei</dc:creator>
      <pubDate>Fri, 12 May 2023 07:29:30 +0000</pubDate>
      <link>https://dev.to/elischei/how-to-upgrade-your-spfx-project-to-the-latest-version-and-how-to-fixavoid-common-issues-2inp</link>
      <guid>https://dev.to/elischei/how-to-upgrade-your-spfx-project-to-the-latest-version-and-how-to-fixavoid-common-issues-2inp</guid>
      <description>&lt;p&gt;Recently I had to upgrade an older project to the newest version of SPfx, and even though there are some great tools to help you on your way you typically run into some errors anyway.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to upgrade your project
&lt;/h2&gt;

&lt;p&gt;You could try to just upgrade the SPfx packages that are listed in package.json. But these might have other dependencies that should also be updated and their packages might have dependencies… and so on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I9kteJIE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tl00x7kwjsn8wx5gdeuy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I9kteJIE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tl00x7kwjsn8wx5gdeuy.png" alt="image of package.json and the dependensies to update" width="622" height="724"&gt;&lt;/a&gt;&lt;br&gt;
So instead I reccomend that you use &lt;a href="https://pnp.github.io/cli-microsoft365/cmd/spfx/project/project-upgrade/"&gt;Microsoft 365 CLI&lt;/a&gt; to generate a report that tells you exactly what to upgrade.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install Microsoft 365 CLI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;npm i -g @pnp/cli-microsoft365&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the project upgrade command to get a upgrade-report for your project&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;m365 spfx project upgrade --toVersion 1.14.0 --output md &amp;gt; "upgrade-report.md"&lt;/code&gt;&lt;br&gt;
The above command will generate a markdown file with the name “upgrade-report”, and this will have a list of all the steps you need to take to upgrade your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common errors and how to fix them (or avoid them)
&lt;/h2&gt;

&lt;p&gt;Even though you follow the report you migh encounter some issues when trying to build your solution afterwards.&lt;/p&gt;

&lt;p&gt;Even though you follow the report you migh encounter some issues when trying to build your solution afterwards.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Check for duplicate dev-dependencies
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--neD_D1Zw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z297fav9tgn3blle5wch.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--neD_D1Zw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z297fav9tgn3blle5wch.png" alt="shows duplicate dependencies in package.json file" width="646" height="229"&gt;&lt;/a&gt;&lt;br&gt;
Even though these are strictly speaking different npm packages you should only have on of them listed as a dependency or they might “get in each others way”. Check the upgrade report for wich version you should use. For me it was "...compiler-3.9": "0.4.47". So I removed the other one.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Delete node_modules, and package-lock.json
&lt;/h3&gt;

&lt;p&gt;To be sure there aren’t any old versions hanging around delete both your node_modules folder and the package-lock.json file and run npm install.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can try npm dedupe before deleting node_modules and package-lock. This might solve any issues related to old versions – thanks to &lt;a href="https://twitter.com/waldekm"&gt;Waldek Mastykarz&lt;/a&gt; for mentioning this on twitter&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3. Deprecated tslint rules
&lt;/h3&gt;

&lt;p&gt;You might need to remove some tslint rules that are no longer valid. The error message will tell you witch rule you need to remove. For me it was the member-access rule.&lt;br&gt;
&lt;code&gt;Error - [tslint] The 'member-access' rule threw an error ...&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. JavaScript heap out of memory
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--T9ivkdOd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ohdn6onwghmnuefmzsr9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T9ivkdOd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ohdn6onwghmnuefmzsr9.png" alt="Shows error message when javascript heap out of memory" width="800" height="283"&gt;&lt;/a&gt;&lt;br&gt;
In my case, since this had something to do with tslint I think what probably solved it was removing the duplicate dependency as shown in the above section. But through my travels in google searches this showed up in multiple issues over differnt versions of SPfx – so I thought I should mention it.&lt;/p&gt;

&lt;p&gt;If you have done the above steps and still gets this error it might be because the task needs more memory to run, so you can try fixing it by setting the --max_old_space_sice to a higher value.&lt;br&gt;
&lt;code&gt;gulp bundle --max_old_space_size=8192 --ship&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In short the steps you shuld take to upgrade your solution is&lt;/p&gt;

&lt;p&gt;Run the M365 CLI project upgrade command&lt;br&gt;
Do all the steps from the report that is generated&lt;br&gt;
Check packacke.json for duplicate dev-dependencies&lt;br&gt;
Try running npm dedupe&lt;br&gt;
Delete node_modules and package-lock.json, and then run npm install.&lt;br&gt;
If you get an error on deprecated tslint rules – delete the rules from the tslint file&lt;br&gt;
If you get an JavaScript heap out of memory error – try adding more memory to the task with&lt;br&gt;
--max_old_space_size=8192&lt;/p&gt;

</description>
    </item>
    <item>
      <title>What is a Microsoft 365 Developer, and how to get started</title>
      <dc:creator>Eli H. Schei</dc:creator>
      <pubDate>Mon, 20 Jun 2022 12:01:44 +0000</pubDate>
      <link>https://dev.to/elischei/what-is-a-microsoft-365-developer-and-how-to-get-started-17mm</link>
      <guid>https://dev.to/elischei/what-is-a-microsoft-365-developer-and-how-to-get-started-17mm</guid>
      <description>&lt;p&gt;Often, when I talk to other developers – outside of the the “Microsoft 365 sphere”, they have no idea what it means to be a “Microsoft 365 Developer”. So I thought I should write about it and try to give an overview of what we do.&lt;/p&gt;




&lt;h2&gt;What does it mean to be a Microsoft 365 Developer?&lt;/h2&gt;

&lt;p&gt;In a lot of aspects – its just like being any other type of developer. You write code, you create things, you use source control, you deploy stuff and so on. Where it differst from ‘regular development’ is that where you typically have a stack of technologies that you use to build a webiste or app of some sort from scratch - in Microsoft 365 you work with a lot of different products which all can be used as is. And the main task of the developer is to extend/build on top of the exisiting capabilites of these products.&lt;/p&gt;

&lt;h3&gt;What even is Microsoft 365?&lt;/h3&gt;

&lt;p&gt;If you are brand new to this area you might not have a clear picture of what Microsoft 365 is, so lets start there. Microsoft 365 (M365) is Microsofts productivity cloud. It is a collection of tools that you can use to work and collaborate with your colleagues. It includes the Office suite (Word, Excel, Power point), OneDrive, SharePoint and Teams.&lt;/p&gt;

&lt;p&gt;And then there is &lt;em&gt;Power Platform&lt;/em&gt;, which is in the same sphere as M365, but still a little on its own. And then there is a logical connection from Power Platform to &lt;em&gt;Dynamics 365&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;And of course there is &lt;em&gt;Azure&lt;/em&gt; – with Azure AD, and app registrations that play a big part in M365 development. To make it more confusing there are different development lifecycles and tools for a lot of these different products.&lt;/p&gt;

&lt;h3&gt;So what do a Microsoft 365 developer typically do?&lt;/h3&gt;

&lt;p&gt;Work patterns and workflows will differ between companies – so even though a lot of companies use the same (M365) tools – they might want to use them differently. Thats why Microsoft supports all kinds of different ways to extend M365. It is possible to build custom apps that give you total control of the user experience, or you can extend existing functionallity with smaller changes/extensions.&lt;/p&gt;

&lt;p&gt;As I mentioned previously we typically “extend the capabilities of the products in the Microsoft 365 sphere”, or add new capabilites. Or we create the links between different M365 products so they can ‘talk to each other’.&lt;/p&gt;




&lt;h2&gt;How can you build on top of Microsoft 365?&lt;/h2&gt;

&lt;p&gt;So this is where it gets fun – and also kind of overwhelming.&lt;/p&gt;

&lt;p&gt;SharePoint webparts, Teams apps, Teams extensions, Teams bots, SPfx apps, SPfx extensions, Office add ins, Power Apps (no code/low code), PCF components….. you might have heard of all of these, some of them, or none of them. As mentioned there are a lot of ways to build on top of Microsoft 365 and I’ll try to give you a simplified overview.&lt;/p&gt;

&lt;p&gt;To do this lets divide Microsoft 365 into four main developer areas: SharePoint Online, Teams, Power Platform and Office.&lt;/p&gt;

&lt;h3&gt;SharePoint Online&lt;/h3&gt;

&lt;p&gt;SharePoint is a collaboration tool that offers a simple way to create pages, lists and work on documents together. It is often used as an intranet solution, where you can find internal news, tools and documentation.&lt;/p&gt;

&lt;p&gt;There are different ways to extend SharePoint. You can &lt;a href="https://docs.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/overview-client-side-web-parts"&gt;crete webparts&lt;/a&gt; (apps) and you &lt;a href="https://docs.microsoft.com/en-us/sharepoint/dev/spfx/extensions/overview-extensions"&gt;can create extensions&lt;/a&gt;. You can use the same framwork for these, and that is &lt;a href="https://docs.microsoft.com/en-us/sharepoint/dev/spfx/sharepoint-framework-overview"&gt;SharePoint Framework&lt;/a&gt; – also called SPfx for short. SPfx is a framwork for client side SharePoint development, and it uses JavaScript/TypeScript and React. There are tools and examples that will show you how to use something other than React if you prefer.&lt;/p&gt;

&lt;h3&gt;Teams&lt;/h3&gt;

&lt;p&gt;Most people think of Teams as a meeting and chat tool – which is not wrong – but Teams is actually built on top of SharePoint as a collaboration tool - an easy way to work in teams and share documents, tasks etc.&lt;/p&gt;

&lt;p&gt;From a developer perspective – how do you extend Teams? You can &lt;a href="https://docs.microsoft.com/en-us/learn/modules/intro-microsoft-teams-apps/2-microsoft-teams-apps"&gt;build apps&lt;/a&gt;, embed a webpage in a &lt;a href="https://docs.microsoft.com/en-us/learn/modules/embedded-web-experiences/"&gt;Teams tab&lt;/a&gt;, create &lt;a href="https://docs.microsoft.com/en-us/learn/modules/msteams-conversation-bots/"&gt;conversational bots&lt;/a&gt; to solve different tasks, you can create &lt;a href="https://docs.microsoft.com/en-us/learn/modules/msteams-messaging-extensions/"&gt;message extensions&lt;/a&gt;, or collect user input with something that’s called ‘&lt;a href="https://docs.microsoft.com/en-us/learn/modules/msteams-task-modules/"&gt;task modules&lt;/a&gt;‘ (wich is basically pop-ups/modals). And you can connect to different services using &lt;a href="https://docs.microsoft.com/en-us/learn/modules/msteams-webhooks-connectors/"&gt;webhooks or Office 365 connectors&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can actually use &lt;a href="https://docs.microsoft.com/en-us/microsoftteams/platform/sbs-gs-spfx?tabs=vscode%2Cviscode"&gt;SharePoint Framework to build apps for Teams&lt;/a&gt;, or you can use the &lt;a href="https://docs.microsoft.com/en-us/microsoftteams/platform/toolkit/visual-studio-code-overview"&gt;Teams toolkit&lt;/a&gt;. The toolkit also &lt;a href="https://devblogs.microsoft.com/visualstudio/build-apps-for-microsoft-teams-with-net/"&gt;supports development in .NET&lt;/a&gt; if you are more comfortable backend.&lt;/p&gt;

&lt;h3&gt;Power Platform&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Power Apps&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Power apps is itself a tool for creating apps. It provides an easy no-code/low-code drag and drop solution to build apps. But you also have Power Apps Component framework that lets you create your own component that can be used inside a power app. These components can also be used inside Dynamics 365.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Power automate&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Power automate is a service to help you create workflows. This is also a low-code solution where you can drag and drop different steps together to create your flow. This is an easy way to get the different parts of M365 talking together.&lt;/p&gt;

&lt;h3&gt;Office&lt;/h3&gt;

&lt;p&gt;Most people use the office suite and never conciders that it can be extended with add-ins. An &lt;a href="https://docs.microsoft.com/en-us/office/dev/add-ins/overview/learning-path-beginner" rel="noreferrer noopener" title="Office add-in is almost like a miniature webapp that embedded in the office clients"&gt;Office add-in is almost like a miniature webapp that embedded in the office clients&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;Azure&lt;/h3&gt;

&lt;p&gt;Ok, so Azure is strictly speaking not a part of Microsoft 365, but as a Microsoft 365 developer you should still be familiar with some parts of it. The most important part (from a M365 developer perspective) is &lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app" rel="noreferrer noopener" title="Azure App registrations"&gt;Azure App registrations&lt;/a&gt; which we use to grant the apps/extensions access to resources. Azure functions are also very useful, but in my personal definition of M365 Development I don’t consider Azure Functions part of it so I won’t cover that here. &lt;/p&gt;

&lt;h3&gt;Microsoft Graph&lt;/h3&gt;

&lt;p&gt;Another tool you should know about if you want to get started with Microsoft 365 Development is &lt;a href="https://docs.microsoft.com/en-us/graph/overview" rel="noreferrer noopener" title="Microsoft Graph"&gt;Microsoft Graph&lt;/a&gt;. This is an API that you can use to get information from different parts of M365. This can be current user, documents, list elements and so on. You can also use it to edit/add information, &lt;a href="https://elischei.com/upload-files-to-sharepoint-with-javascript-using-microsoft-graph/" rel="noreferrer noopener" title="upload files"&gt;upload files&lt;/a&gt; ++. &lt;/p&gt;




&lt;h2&gt;How to get started as a Microsoft 365 developer?&lt;/h2&gt;

&lt;p&gt;First you should &lt;a href="https://developer.microsoft.com/en-us/microsoft-365/dev-program"&gt;sign up for the Microsoft 365 Developer program&lt;/a&gt;. It is free and it will give you access to your own M365 developer tenant that you can use to test the apps/extensions that you build.&lt;/p&gt;

&lt;p&gt;When working with Power Apps you also &lt;a href="https://powerapps.microsoft.com/en-us/developerplan/"&gt;need to get the Power Apps developer plan&lt;/a&gt;  (this is also free).&lt;/p&gt;

&lt;p&gt;And from there - start by following some guides/tutorials and just jump into it. I’ve added a lot of links to different resources in the previous sections, but I’ll also add a list of links in the end of this blogpost.&lt;/p&gt;

&lt;h3&gt;Frontend or backend&lt;/h3&gt;

&lt;p&gt;A lot of the M365 developer toolkits are offered for both .NET and JavaScript/TypeScript, but you don’t always have a choice. The best is probably to be comfortable in both worlds.&lt;/p&gt;

&lt;p&gt;In my experience a lot of the M365 development are now client-side focused, and you can almost always find an example on how to do something in JavaScript/TypeScript. But since I’m a frontend developer I haven’t really looked for that many backend resources - so there might be many out there. I can only speak from my own experience and I will always choose TypeScript (or JavaScript) if I can – but I know enough C#/.NET to do small simple things if I absolutely have to. And that combination of skills works great for me.&lt;/p&gt;




&lt;h2&gt;Resources&lt;/h2&gt;

&lt;p&gt;I've previusly written a blogpost "&lt;a href="https://elischei.com/a-collection-of-resources-for-microsoft-365-developers/" title="A collection of resources for Microsoft 365 Developers"&gt;A collection of resources for Microsoft 365 Developers&lt;/a&gt;" so take a look at that too. But here are some good resources if you are completely new to this area of development.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=2JWUr6zBtwg" rel="noreferrer noopener" title="Introduction to the Microsoft 365 Developer program"&gt;Introduction to the Microsoft 365 Developer program&lt;/a&gt; (youtube video)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.microsoft.com/en-us/microsoft-365/dev-program" rel="noreferrer noopener" title="Microsoft 365 Developer program"&gt;Microsoft 365 Developer program&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/en-gb/learn/paths/m365-extend-fundamental/" rel="noreferrer noopener" title="Extend Microsoft 365 – Fundamental"&gt;Extend Microsoft 365 – Fundamental&lt;/a&gt; (Microsoft Learn module)&lt;/li&gt;
&lt;li&gt;I&lt;a href="https://docs.microsoft.com/en-us/sharepoint/dev/spfx/sharepoint-framework-overview" rel="noreferrer noopener" title="ntroduction to SharePoint Framwork"&gt;ntroduction to SharePoint Framwork&lt;/a&gt; (Microsoft docs)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=EQuB8l4sccg&amp;amp;list=PLWZJrkeLOrbblzC_s22pIBOotBV66erf-" title="Getting started with Teams app"&gt;Get started building Microsoft Teams apps (youtube course)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://elischei.com/category/m365dev/microsoft-teams/" rel="noreferrer noopener" title="My previous blogposts about Teams development"&gt;My previous blogposts about Teams development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://elischei.com/category/m365dev/sharepoint-online/" rel="noreferrer noopener" title="My previous blogposts about SharePoint development"&gt;My previous blogposts about SharePoint development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://elischei.com/a-comprehensive-guide-to-power-apps-component-framework-pcf-part-1-getting-started/" rel="noreferrer noopener" title="A comprehensive guide to PCF components"&gt;A comprehensive guide to PCF components&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Did you find this article usefull? &lt;a href="https://twitter.com/acupof_dev"&gt;Follow me on twitter&lt;/a&gt; to be notified when I publish something new!&lt;/p&gt;

&lt;p&gt;Also, if you have any feedback or questions, please let me know in the comments below. 🙂&lt;/p&gt;

&lt;p&gt;Thank you for reading!&lt;/p&gt;

&lt;p&gt;/Eli&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Upload files to SharePoint with JavaScript using Microsoft Graph and Microsoft Authentication Library</title>
      <dc:creator>Eli H. Schei</dc:creator>
      <pubDate>Tue, 23 Nov 2021 09:00:28 +0000</pubDate>
      <link>https://dev.to/elischei/upload-files-to-sharepoint-with-javascript-using-microsoft-graph-and-microsoft-authentication-library-kml</link>
      <guid>https://dev.to/elischei/upload-files-to-sharepoint-with-javascript-using-microsoft-graph-and-microsoft-authentication-library-kml</guid>
      <description>&lt;p&gt;Phu, thats a long title - but I wanted to make it really clear what this blogpost is about. So as you might have guessed, in this blogpost I will cover how to upload files to SharePoint with JavaScript using Microsoft Graph for the request, and Microsoft Authentication Library for authentication.&lt;/p&gt;

&lt;p&gt;I recently had to solve this for a client, and I used a lot of time banging my head against the wall looking for resources.  It was not really the lack of resorces that was the issue - but that every example was either to big - or it took for granted that I had some sort of understanding that I was obviously lacking. So when I finally figured out how to do it - and how little code it actually requires - I decided that I needed to blog about it. Hopefully this blogpost will save you some time! &lt;/p&gt;

&lt;p&gt;I also mada a small vuejs app so you can get up and running quicly. My goal was to present you with the bare minimum amount of code that you need - and hopefully you can build on top of that. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Prerequesites: &lt;/strong&gt;You should know basic programming, and have an understanding of working against an API - and different authentication flows.&lt;/p&gt;

&lt;p&gt;
&lt;strong&gt;Source code: &lt;/strong&gt;You can find the &lt;a href="https://github.com/Eli-Schei/upload-files-to-sp-using-graph" rel="noopener"&gt;full source code for this example on my github&lt;/a&gt;. Note, this is a stripped down example to show you the minimum of what you need to upload a file. Its a good baseline/starting point to build on. 
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;Table of contents:&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Creating an app registration for a single page application in Azure AD&lt;/li&gt;
&lt;li&gt;Authenticating with MSAL&lt;/li&gt;
&lt;li&gt;Handling the file using FileReader&lt;/li&gt;
&lt;li&gt;Making request to graph&lt;/li&gt;
&lt;li&gt;Resources&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;

&lt;p&gt;There are four steps you need to complete when uploading files from a javascript app with graph. Lets have a quick look at each of them before we go into the details.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You need to register a single page application (SPA) in Azure Acive Directory (AAD). &lt;ul&gt;&lt;li&gt;You will use this to authenticate your users.&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;You need to use Microsoft Authentication library (msal) to authenticate against the SPA you create in the first step.&lt;ul&gt;&lt;li&gt;So you know who wants to upload a file - and that they have permission to do so.&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;You need to handle the file the user has selected. &lt;ul&gt;&lt;li&gt;Microsoft Graph accepts ArrayBuffer, Buffer or Blob objects.&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;You need to make a request to Microsoft Graph with an Authentication Token from msal, and the file your user has selected.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Maybe you allready know how to do some of these steps, or maybe you are new to all of them. In the rest of this blogpost I will cover every step in detail. I also provide you with a list of resources. &lt;/p&gt;

&lt;h2 id="register-app"&gt;Creating an app registration for a single page application in Azure AD&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Since you are reading this blogpost I'll asume that you allready have a Microsoft 365 tenant where you would like to upload the documents. If not you can &lt;a href="https://developer.microsoft.com/en-us/microsoft-365/dev-program" rel="noreferrer noopener" title="https://developer.microsoft.com/en-us/microsoft-365/dev-program"&gt;register for a free dev tenant her&lt;/a&gt;. &lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you don't have admin priveleges to Azure AD you need to get somenone who does to register the app for you. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; Log in to &lt;a href="https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/Overview" rel="noreferrer noopener" title="https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/Overview"&gt;Azure Active Directory&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; In the menu on the left select App registrations&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XpOfctyh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://elischei.com/wp-content/uploads/2021/11/image-9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XpOfctyh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://elischei.com/wp-content/uploads/2021/11/image-9.png" alt="Upload files to SharePoint with JavaScript using Microsoft Graph you need to first register an app in azure" width="412" height="729"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3.Select "New registration&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.&lt;/strong&gt; Fill in the name, select the account types you would like to support. And set the Redirect URI type to "Single-page application (SPA)". &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note, the URI you fill in must match the url where your app is running. In my example code that is localhost:3000. You can change this URI later when the code is running from somewhere else.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fUvG8QlG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://elischei.com/wp-content/uploads/2021/11/image-11-1024x619.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fUvG8QlG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://elischei.com/wp-content/uploads/2021/11/image-11-1024x619.png" alt="" width="880" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click "Register". On the app info page copy down the Application (client) ID, and the Directory (tenant) ID. 
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SDnxdgRP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://elischei.com/wp-content/uploads/2021/11/image-12-1024x352.png" alt="App registration landing page with App id and tenant ID hightlightet. " width="880" height="303"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Thats it. You now have a single page app registration.&lt;/p&gt;

&lt;h2 id="auth-with-msal"&gt;Authenticating with Microsoft Authentication Library&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Example code&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;
I have made a small vue app to give you an example that you can actually run right away. But all the logic is written in vanilla javascript so you don't need to know vuejs to use the example. &lt;a href="https://github.com/Eli-Schei/upload-files-to-sp-using-graph"&gt;You can find the source code here&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Information on how to get the example code up and running is &lt;a href="https://github.com/Eli-Schei/upload-files-to-sp-using-graph#readme"&gt;documentet in the repos readme file&lt;/a&gt; so I will not cover that in this blogpost. &lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To be able to upload a document we first need to authenticate the user against the SPA you have registered in Azure AD.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configuration&lt;/strong&gt;&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;msalConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;YOUR APP ID FROM AZURE REGISTRATION&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;authority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://login.microsoftonline.com/YOUR_TENANT_ID&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;//This URL must match the one set in azure app reg&lt;/span&gt;
    &lt;span class="na"&gt;redirectUri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:3000/&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;msalRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;scopes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User.Read&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Files.ReadWrite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Files.ReadWrite.All&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First we create and initialize an msal-client.  This is what we'll use to communicate with the Azure SPA and authenticate the user.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;msalClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;msal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PublicClientApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msalConfig&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we write a function to handle the login. This is done by using the msal-client and calling the loginPopup function with the scopes we created in the configuration.&lt;/p&gt;

&lt;p&gt;You can also add functionallity to get the token silently first if the user is allready logged in - so the user is not promted to log in every time. But since I wanted to keep this code sample as small as possible I left this out here, but you can see an example in the next code snippet.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;signInWithMsal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;msalClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loginPopup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msalRequest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;sessionStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;msalAuthName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;authResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&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;We also have a function to get the msal token. This function is used in the next step when we call Graph. Here you can also se an example of ataining the token silently.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getMsalToken&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sessionStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;msalAuthName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;silentRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;scopes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;msalRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scopes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;account&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;msalClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAccountByUsername&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;silentResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;msalClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;acquireTokenSilent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;silentRequest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;silentResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;//Add handling for new login promt here - if the silent request should fail&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;h2 id="handle-file"&gt;Handling the selected file&lt;/h2&gt;

&lt;p&gt;Graph will axcept the file as an ArrayBuffer, a Buffer or a Blob. In my example we use a filereader object to read the file as an ArrayBuffer and send it to the uploadDocument function. &lt;/p&gt;

&lt;p&gt;Obtain the filename and the file itself from the input field. &lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
          &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;selectedFile&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileToUplode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
          &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;selectedFile&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a FileReader and a function that will run when the FileReader is loading. Then call the readFileAsArrayBuffer function passing in the file. The onload function has an event parameter 'event.target.result' will contain the ArrayBuffer version of the selected file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;filereader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;uploadDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="c1"&gt;//This will trigger the onload function above.&lt;/span&gt;
&lt;span class="nx"&gt;filereader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readAsArrayBuffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileToUplode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Complete code for handling the file and calling uploadDocument().&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&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="c1"&gt;//prevents the site from reloading&lt;/span&gt;
      &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="c1"&gt;// sign the user in&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;signInWithMsal&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="c1"&gt;//obtain the filename from the file&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;selectedFile&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="c1"&gt;//obtain the file itself&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileToUplode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
          &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;selectedFile&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="c1"&gt;//create filereader&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filereader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;FileReader&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="c1"&gt;//create function that will run when filereader is loading&lt;/span&gt;
      &lt;span class="nx"&gt;filereader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&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="c1"&gt;//call uploadDocument function and pass in filename and file as ArrayBuffer&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;uploadDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="c1"&gt;//call the readAsArrayBuffer on fileReader and pass inn file.&lt;/span&gt;
      &lt;span class="c1"&gt;//This will trigger the onload function above.&lt;/span&gt;
      &lt;span class="nx"&gt;filereader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readAsArrayBuffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileToUplode&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;h2 id="graph-request"&gt;Making a request to graph&lt;/h2&gt;

&lt;p&gt;Now that the authenitcation is handled we can go ahead an make a request to Microsoft Graph. First we need to build the url to use with the request. Then we need to handle the file so it can be sent with the request, and lastly we need to send the request to graph. &lt;/p&gt;

&lt;h3&gt;Building the graph url to use&lt;/h3&gt;

&lt;p&gt;I decided to write a section on how to build your graph-url since I thought it was difficult to figure out exactly what it should contain. &lt;/p&gt;

&lt;p&gt;This is how the url should look:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;uploadURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://graph.microsoft.com/v1.0/sites/&amp;lt;YOUR DOMAIN, SOME_ID, SOME_OTHER_ID&amp;gt;/drive/root:/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
 &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;:/content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I think "SOME_ID" should be the Site-id, and the "SOME_OTHER_ID" should be the web-id. But instead of looking these up I found a graph request that will return the complete id including domian.&lt;/p&gt;

&lt;p&gt;To attain it just run the below request in &lt;a href="https://developer.microsoft.com/en-us/graph/graph-explorer" rel="noreferrer noopener" title="https://developer.microsoft.com/en-us/graph/graph-explorer"&gt;Graph Explorer&lt;/a&gt; (or Postman). &lt;/p&gt;

&lt;p&gt;N&lt;em&gt;ote, to run this request you need to include a bearer token. If you do it from graph explorer it does this for you when you log in. If you do it from postman you need to get the access token first - and then run the below request.&lt;/em&gt;&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//graph.microsoft.com/v1.0/sites/YOUR_DOMAIN.sharepoint.com:/sites/NAME_OF_SITE_YOU_WANT_TO_UPLOAD_TO/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will give you a response that contains an id like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tSoB6N0c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://elischei.com/wp-content/uploads/2021/11/image-8-1024x134.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tSoB6N0c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://elischei.com/wp-content/uploads/2021/11/image-8-1024x134.png" alt="" width="880" height="115"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy the whole "id" and put it in your uploadURL&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//graph.microsoft.com/v1.0/sites/PUT_THE_ID_FROM_PREVIOUS_STEP_HERE/drive/root:/"&lt;/span&gt;
 &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;:/content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;Making the request&lt;/h3&gt;

&lt;p&gt;There is a Microsoft Graph SDK for javascript, but for this example I'm using a regular window.fetch request instead of creating a graphClient. To learn more about the Graph SDK see links listed in Resources. &lt;/p&gt;

&lt;p&gt;We pass our uploadURL as the first parameter to fetch. The secod parameter is an object that contains the header with the authorization Bearer token, and a body that contains the file. &lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;uploadDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fileToUpload&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;uploadURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://graph.microsoft.com/v1.0/sites/&amp;lt;YOUR DOMAIN, SITE, AND WEB ID HERE &amp;gt;/drive/root:/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;:/content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uploadURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PUT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;getMsalToken&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fileToUpload&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;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&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="c1"&gt;// Here you can implement some user feedback. "File uploaded" etc.. &lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ERROR UPLOADING&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;And thats it. You have now uploaded a file to SharePoint! &lt;/p&gt;

&lt;h3&gt;Working with large files&lt;/h3&gt;

&lt;p&gt;If you are working with larger files (4MB+) you could use an upload session to handle the request. See links in Resources below for more information about that. &lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/@microsoft/microsoft-graph-client" rel="noreferrer noopener" title="https://www.npmjs.com/package/@microsoft/microsoft-graph-client"&gt;Microsoft Graph JavaScript Client Library &lt;/a&gt;- npm site.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/en-us/graph/sdks/create-requests?tabs=TypeScript" rel="noreferrer noopener" title="https://docs.microsoft.com/en-us/graph/sdks/create-requests?tabs=TypeScript"&gt;Make API calls using the Microsoft Graph SDK&lt;/a&gt; - Microsoft docs&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/en-us/graph/api/driveitem-createuploadsession?view=graph-rest-1.0&amp;amp;preserve-view=true" rel="noreferrer noopener" title="https://docs.microsoft.com/en-us/graph/api/driveitem-createuploadsession?view=graph-rest-1.0&amp;amp;preserve-view=true"&gt;Upload a large file with a upload session&lt;/a&gt; - Microsoft docs&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=YYMFP8xcNOQ" rel="noreferrer noopener" title="https://www.youtube.com/watch?v=YYMFP8xcNOQ"&gt;Upload small or large files using Graph&lt;/a&gt; - YouTube, Microsoft 365 Developer channel&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/microsoftgraph/msgraph-sdk-javascript" rel="noreferrer noopener" title="https://github.com/microsoftgraph/msgraph-sdk-javascript"&gt;Microsoft Graph JavaScript Client Library&lt;/a&gt; - GitHub, Microsoft Graph repo&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/en-us/graph/tutorials/javascript" rel="noreferrer noopener" title="https://docs.microsoft.com/en-us/graph/tutorials/javascript"&gt;Build JavaScript single page apps with Graph&lt;/a&gt; - Tutorial - Microsoft docs&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Did you find this article usefull? &lt;a href="https://twitter.com/acupof_dev"&gt;Follow me on twitter&lt;/a&gt; to be notified when I publish something new!&lt;/p&gt;

&lt;p&gt;Also, if you have any feedback or questions, please let me know in the comments below. 🙂&lt;/p&gt;

&lt;p&gt;Thank you for reading, and happy coding!&lt;/p&gt;

&lt;p&gt;/Eli&lt;/p&gt;

</description>
      <category>sharepoint</category>
      <category>m365</category>
      <category>javascript</category>
      <category>microsoftgraph</category>
    </item>
    <item>
      <title>Testing Teams apps made easier with the new developer portal</title>
      <dc:creator>Eli H. Schei</dc:creator>
      <pubDate>Fri, 12 Nov 2021 13:06:48 +0000</pubDate>
      <link>https://dev.to/elischei/testing-teams-apps-made-easier-with-the-new-developer-portal-1m4j</link>
      <guid>https://dev.to/elischei/testing-teams-apps-made-easier-with-the-new-developer-portal-1m4j</guid>
      <description>&lt;p&gt;One of my most read blogposts is&lt;a href="https://elischei.com/enable-sideloading-of-apps-in-microsoft-teams/"&gt;the one about sideloading apps in Microsoft Teams&lt;/a&gt;, so when I heard about the developer portal and how it makes it easier to test Teams apps I thought I should write about that too. The developer portal was made general available for all Teams developers in october this year (2021). I really like that you get both resources and tools presented in the same place. And of course that they have made it very easy too test Teams apps.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note! Since I have allready been testing Teams apps before, I have &lt;a href="https://elischei.com/enable-sideloading-of-apps-in-microsoft-teams/"&gt;enabled both sideloading&lt;/a&gt; and the &lt;a href="https://docs.microsoft.com/en-us/microsoftteams/teams-custom-app-policies-and-settings#org-wide-custom-app-setting"&gt;‘allow interaction with cusom apps’ setting&lt;/a&gt; on my dev-tenant. I have not tried to test an app from the developer portal without these settings – so its possible you still have to enable them to use the developer portal for testing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How to test teams apps through the developer portal
&lt;/h2&gt;

&lt;p&gt;Start by navigating to the developer portal, you can find it here: &lt;a href="https://dev.teams.microsoft.com/home"&gt;https://dev.teams.microsoft.com/home&lt;/a&gt; . If you are not allready logged in – do so.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--plIn-sPB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vj0g6shpdt0qvbrbyv2u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--plIn-sPB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vj0g6shpdt0qvbrbyv2u.png" alt="Devportal frontpage" width="880" height="457"&gt;&lt;/a&gt;&lt;br&gt;
In the navigation on the left side, select Apps. This will show you the apps that you have allready added. There are also shortcuts to create a new app (I havn’t tested this yet) or import an existing app. In this blogpost I will assume you allready have an app you want to test, so either import it, or select it from the list.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v1l8olcG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/crpb99o450cc83vje1n1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v1l8olcG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/crpb99o450cc83vje1n1.png" alt="Devportal all apps page" width="880" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you select an app you will get a landing page for that specific app. Here you can find a lot of usefull information about the app, and you can also change some configurations from here.&lt;/p&gt;

&lt;p&gt;In the upper right corner you will see a button that sais “Preview in Teams”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ceil_fGG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8lavv22nqg34p94ftffj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ceil_fGG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8lavv22nqg34p94ftffj.png" alt='Devportal app overview page with the "preview in teams" button hightlightet' width="880" height="407"&gt;&lt;/a&gt;&lt;br&gt;
When clickling the button you will first get promted to open Teams, and inside Teams you’ll get a dialog to add the app to a teams tab. Click the “Add to a team” button and select the team where you would like the app to be installed.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MoLTdj4L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/76lg9jm86clv2m8ven06.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MoLTdj4L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/76lg9jm86clv2m8ven06.png" alt="The add app to teams dialog" width="880" height="380"&gt;&lt;/a&gt;&lt;br&gt;
And thats it, now you can test your app inside teams. 🙂&lt;/p&gt;

&lt;h2&gt;
  
  
  Pro tip: Add the developer portal as an app in Teams
&lt;/h2&gt;

&lt;p&gt;The developer portal is actually available as a Teams app itself. Install it and you can manage and test your Teams applications directly from teams.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aiko_HSp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zshdcjmabp3vgw0mxw8g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aiko_HSp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zshdcjmabp3vgw0mxw8g.png" alt="Devportal added as an app inside teams" width="880" height="708"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://devblogs.microsoft.com/microsoft365dev/manage-your-microsoft-teams-apps-with-the-developer-portal/"&gt;Manage your Microsoft Teams apps with the Developer Portal – Microsoft 365 Developer Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/build-and-test/teams-developer-portal"&gt;Manage your apps with the Developer Portal – Teams | Microsoft Docs&lt;/a&gt;
***
Did you find this article usefull? &lt;a href="https://twitter.com/acupof_dev"&gt;Follow me on twitter&lt;/a&gt; to be notified when I publish something new!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, if you have any feedback or questions, please let me know in the comments below. 🙂&lt;/p&gt;

&lt;p&gt;Thank you for reading, and happy coding!&lt;/p&gt;

&lt;p&gt;/Eli&lt;/p&gt;

</description>
    </item>
    <item>
      <title>5 reasons I started a developer blog and why you should concider starting one too</title>
      <dc:creator>Eli H. Schei</dc:creator>
      <pubDate>Wed, 03 Nov 2021 09:21:59 +0000</pubDate>
      <link>https://dev.to/elischei/5-reasons-i-started-a-developer-blog-and-why-you-should-concider-starting-one-too-2kml</link>
      <guid>https://dev.to/elischei/5-reasons-i-started-a-developer-blog-and-why-you-should-concider-starting-one-too-2kml</guid>
      <description>&lt;p&gt;After a two month “blogging dry spell” it might be a little ironic that now is when I decide to write a blogpost about blogging. But I’d like to get back into the habit of writing regularly, and I think you should consider it too! In this blogpost I will explain why.&lt;/p&gt;

&lt;p&gt;After a decade as a front-end developer I finally started a developer/tech-blog in february 2021. Why now? Why not 5 years ago, or 10 years ago? The short answer is “imposter syndrome”. I felt like everything was written before and/or I didn’t know enough about a subject to blog about it. None of these are good reasons for not blogging.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. You have a unique point of view
&lt;/h2&gt;

&lt;p&gt;It does not matter if you have worked as a developer for years, or if you are just starting out. Your point of view are unique. Your ways of explaining something is unique, and even though there are hundreds of blogposts about a subject your blogpost might be the one that will help someone else.&lt;/p&gt;

&lt;p&gt;In my experience I can read multiple different blogposts about exactly the same topic, and only one of them makes sense to me. Thats why I decided to add my voice to the mix – and thats why there are always room for more bloggers!&lt;/p&gt;

&lt;h2&gt;
  
  
  2. We wan’t to learn from someone at our own level – or just one step above
&lt;/h2&gt;

&lt;p&gt;Have you ever read a blogpost and thought “I feel like there is something secret written between the lines, and I don’t know what it is”. This can typically be a problem when an expert tries to write something for beginners. The expert have forgotten what it was like when they just started out, and take a lot of knowledge for granted – and without even thinking about it they leave it out of their explanations.&lt;/p&gt;

&lt;p&gt;Thats why you should write about stuff as you’re learning them, or right after. When you still remember all the questions you had, and what type of challanges you met.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. You get a deeper understanding of the subject
&lt;/h2&gt;

&lt;p&gt;The process around writing a blogpost will give you a better understanding of a subject. And probably about some related subjects too.&lt;/p&gt;

&lt;p&gt;For most of my blogposts I try to find some good resources that the reader can benefit from – and that means I have to locate and read those resources myselfe to make sure they are relevant. If I was not blogging I probably would not read as many other blogs either – and I would miss out on the knowledge other people share.&lt;/p&gt;

&lt;p&gt;Writing things down also helps you to remember it better. And it gives you an reference you can go back to later. Like my github cheat sheet I use (and update) regularly.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. You help others avoid the issues you have encountered
&lt;/h2&gt;

&lt;p&gt;At some point in your developer journy you have probably encountered an issue that you have trouble finding good resources on. You know, when you actually go to page 2 on google out of desperation “Someone must have solved this before!?”. And after hours (days/weeks) you are finally able to fit together small pieces of information from multiple sources – and find the solution to your issue.&lt;/p&gt;

&lt;p&gt;The next time this happens you should write about the issue – and the solution – so the next person that is googling it doesn’t need to spend as much time on it! Sharing is caring!&lt;/p&gt;

&lt;h2&gt;
  
  
  5. It can give you opertunities
&lt;/h2&gt;

&lt;p&gt;A lot of developers have portfolios to showcase what they can do. But if you don’t have time to create multiple portfolio projects a blog is a great way to showcase your knowledge, and highlight what you’re most interested in.&lt;/p&gt;

&lt;p&gt;A blogpost can also be a great outline to a conference talk, or even a workshop. You can use it as a baseline if you are sending in a call for papers, or creating an online course.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. You can earn some money
&lt;/h2&gt;

&lt;p&gt;This is not one of my reasons, and it is not a goal for me right now. But that does not mean that it can’t be one of yours. Lots of people make money of their content, here are some great resources you can look into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.compiled.blog/blog/how-i-made-80000-in-2020"&gt;“How I made $80,000 on side projects in 2020” – Emma Bostian, compiled.blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://edidiongasikpo.com/5-ways-developers-can-make-money-through-blogging"&gt;“5 ways developers can make money through blogging” – Edidiong Asikpo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Maybe one day I’ll take this blog ‘to the next level’ and monitize it, but for now I’m happy with keeping it simple and don’t overthink this blogging thing. 🙂&lt;/p&gt;




&lt;p&gt;Did you find this article usefull? &lt;a href="https://twitter.com/acupof_dev"&gt;Follow me on twitter&lt;/a&gt; to be notified when I publish something new!&lt;/p&gt;

&lt;p&gt;Also, if you have any feedback or questions, please let me know in the comments below. 🙂&lt;/p&gt;

&lt;p&gt;Thank you for reading, and happy coding!&lt;/p&gt;

&lt;p&gt;/Eli&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to become a console.log() ninja</title>
      <dc:creator>Eli H. Schei</dc:creator>
      <pubDate>Wed, 22 Sep 2021 12:16:10 +0000</pubDate>
      <link>https://dev.to/elischei/how-to-become-a-console-log-ninja-dk2</link>
      <guid>https://dev.to/elischei/how-to-become-a-console-log-ninja-dk2</guid>
      <description>&lt;p&gt;If you are a web developer I'm guessing you have used console.log() a couple of (thousand) times. But did you know that the console object has some other usefull methods you can use to structure the output you get?&lt;/p&gt;

&lt;h2&gt;What is the console object?&lt;/h2&gt;

&lt;p&gt;First, a very with a short introduction to the console object before we dive in to its methods.&lt;/p&gt;

&lt;p&gt;So what is the console object? The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/console" rel="noreferrer noopener" title="https://developer.mozilla.org/en-US/docs/Web/API/console"&gt;MDN Web docs&lt;/a&gt; sais "The &lt;strong&gt;&lt;code&gt;console&lt;/code&gt;&lt;/strong&gt; object provides access to the browser's debugging console (e.g. the &lt;a href="https://developer.mozilla.org/en-US/docs/Tools/Web_Console" rel="noopener noreferrer"&gt;Web console&lt;/a&gt; in Firefox). The specifics of how it works varies from browser to browser, but there is a &lt;em&gt;de facto&lt;/em&gt; set of features that are typically provided." &lt;/p&gt;

&lt;p&gt;In other words, it is a object that is available to use for debugging purposes. &lt;/p&gt;

&lt;p&gt;Lets take a look at some of the methods it provides. &lt;/p&gt;




&lt;h2&gt;console.table() &lt;/h2&gt;

&lt;p&gt;You have two objects that contains the same structure of information about two pets. You add both pets to an array.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;myPet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Poppy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;favoriteToy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ball&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;myOtherPet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Harry&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pig&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;favoriteToy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;food&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;pets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;myPet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;myOtherPet&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to print the array to the console you can use &lt;code&gt;console.log()&lt;/code&gt;, that will look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb9vmtp07q3up42i8x5h6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb9vmtp07q3up42i8x5h6.png" alt="Image of console.log ouput"&gt;&lt;/a&gt;&lt;br&gt;
If you would like a better overview of what the array contains you can use &lt;code&gt;console.table()&lt;/code&gt; instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pets&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That will give you a nice table presentation of the array content, like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8a442hjir1d8c7aywtrz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8a442hjir1d8c7aywtrz.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;console.group()&lt;/h2&gt;

&lt;p&gt;You can use console.group() to create collapsible groups of outputs. For instance you can use it to group output from functions.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;function1&lt;/span&gt; &lt;span class="o"&gt;=&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Function 1 output&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;this is a message from function1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupEnd&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;function2&lt;/span&gt; &lt;span class="o"&gt;=&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Other function output&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Well hello there!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupEnd&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;function1&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;function2&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the functions are called you will get the messages presented like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff0vsc7sjefk9di4y4mcs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff0vsc7sjefk9di4y4mcs.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nested groups&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can also nest groups inside eachother&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;function2&lt;/span&gt; &lt;span class="o"&gt;=&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Other function output&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Well hello there!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This group is nested inside of the 'Other function output' group&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello from inside this group&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupEnd&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupEnd&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;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqiijsdmjbvdio2rurg7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqiijsdmjbvdio2rurg7.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;collapsed groups&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you want the groups to collapsed as default you can use &lt;code&gt;console.groupCollapsed("name of group")&lt;/code&gt; instead of &lt;code&gt;console.group("name of group")&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;console.dir()&lt;/h2&gt;

&lt;p&gt;When you want to output information about an object in a structured manner you can also use &lt;code&gt;console.dir(object);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9muyilbh9q0molmk0jxi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9muyilbh9q0molmk0jxi.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;console.assert()&lt;/h2&gt;

&lt;p&gt;If you want some condition to decide if your ouput is displayed in the console, &lt;code&gt;console.assert()&lt;/code&gt; is the function for you. This function takes two parameters, a boolean and a string. The message (string) will only be displayed in the console if the boolean value is &lt;code&gt;false&lt;/code&gt;.  &lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;function1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;condition&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This message will be displayed as a warning if the condition equals false&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="nf"&gt;function1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffyoo6m4pg3s6tsxd8gil.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffyoo6m4pg3s6tsxd8gil.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;Adding color to your console output&lt;/h2&gt;

&lt;p&gt;The console object have two built in functions that will add color to the displad text. These are console.warn() and console.error(). And as you might have guessed they will be displayed as a warning and an error.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fswtsefstpg0jks4u8q4c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fswtsefstpg0jks4u8q4c.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Add your own styling&lt;/h3&gt;

&lt;p&gt;If you add %c before your string, and pass a string of styling as a second parameter you can style your output.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Filto9etcm91ecicwrn7v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Filto9etcm91ecicwrn7v.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;Other usefull console methods&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Create and use a timer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can use&lt;code&gt; console.time()&lt;/code&gt; to start a timer, and &lt;code&gt;console.timeEnd() &lt;/code&gt;to end it. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where is your function being called?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;console.trace()&lt;/code&gt; to see where the function was called from&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/console" rel="noreferrer noopener" title="https://developer.mozilla.org/en-US/docs/Web/API/console"&gt;console &lt;/a&gt;(MDN)&lt;/li&gt;&lt;/ul&gt;




&lt;p&gt;Did you find this article usefull? &lt;a href="https://twitter.com/acupof_dev" rel="noopener noreferrer"&gt;Follow me on twitter&lt;/a&gt; to be notified when I publish something new!&lt;/p&gt;

&lt;p&gt;Also, if you have any feedback or questions, please let me know in the comments below. :)&lt;/p&gt;

&lt;p&gt;Thank you for reading!&lt;/p&gt;

&lt;p&gt;/Eli&lt;/p&gt;

</description>
      <category>console</category>
      <category>tips</category>
    </item>
    <item>
      <title>My top 5 favorite newsletters to keep up with frontend development news</title>
      <dc:creator>Eli H. Schei</dc:creator>
      <pubDate>Fri, 10 Sep 2021 07:38:01 +0000</pubDate>
      <link>https://dev.to/elischei/my-top-5-favorite-newsletters-to-keep-up-with-frontend-development-news-170j</link>
      <guid>https://dev.to/elischei/my-top-5-favorite-newsletters-to-keep-up-with-frontend-development-news-170j</guid>
      <description>&lt;p&gt;It can be overwhelming to keep track of everything in the tech-universe - things changes so fast. And I have spent too much time on twitter, online newspapers and forums, scrolling my life away as I look for the things that are relevant for me and my developer journey. And then I realised I should let someone else do the scrolling. So I subscribed to a lot of newsletters  (and then unsubscribed to the ones that didn't quite give me what I wanted).&lt;/p&gt;

&lt;p&gt;I usually just scan through the newsletters and save the links I want to read in &lt;a href="https://getpocket.com/" rel="noreferrer noopener"&gt;pocket&lt;/a&gt;. Then I try to block a 30min session in my calendar 2-3 times a week to actually read the things I save. &lt;/p&gt;

&lt;p&gt;Here are the top 5 newsletters I subscribe to - and actually read. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.stefanjudis.com/newsletter/" rel="noreferrer noopener" title="https://www.stefanjudis.com/newsletter/"&gt;&lt;strong&gt;Stephan's Web Weekly&lt;/strong&gt;&lt;/a&gt;I love the mix of humor and usefull tips and tricks.
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://javascriptweekly.com/" rel="noreferrer noopener" title="https://javascriptweekly.com/"&gt;&lt;strong&gt;JavaScript Weekly&lt;/strong&gt;&lt;/a&gt;Nice collection of news, tips, tutorials, opinions and stories.
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://frontendfoc.us/" rel="noreferrer noopener" title="https://frontendfoc.us/"&gt;&lt;strong&gt;Frontend focus&lt;/strong&gt;&lt;/a&gt;Also a mix of news, tutorials, articles and stories. 
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.a11yproject.com/newsletter/" rel="noreferrer noopener" title="https://www.a11yproject.com/newsletter/"&gt;&lt;strong&gt;The A11y project newsletter&lt;/strong&gt;&lt;/a&gt;As the name suggests this newsletter is related to news in the accessibility (a11y for short) space
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/" rel="noreferrer noopener" title="https://dev.to/"&gt;&lt;strong&gt;DEV Community Digest&lt;/strong&gt;&lt;/a&gt;This is not really a news letter, but if you create a profile here on on &lt;a href="https://dev.to" rel="noreferrer noopener" title="https://dev.to"&gt;dev.to&lt;/a&gt; you will get regular emails with links to articles based on your interests. 
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do you know about any good newsletters I should check out? &lt;/p&gt;

</description>
      <category>newsletter</category>
    </item>
    <item>
      <title>How to register an application in Azure AD using Azure CLI</title>
      <dc:creator>Eli H. Schei</dc:creator>
      <pubDate>Thu, 02 Sep 2021 06:01:33 +0000</pubDate>
      <link>https://dev.to/elischei/how-to-register-an-application-in-azure-ad-using-azure-cli-1b9</link>
      <guid>https://dev.to/elischei/how-to-register-an-application-in-azure-ad-using-azure-cli-1b9</guid>
      <description>&lt;p&gt;If you are working as a M365 developer you probably have had to register an application i Azure AD at some point. In this blogpost I will show you how you can do so using Azure CLI.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Prerequesites:&lt;/strong&gt; You need to &lt;a href="https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-windows?tabs=azure-cli" rel="noopener noreferrer"&gt;download and install Azure CLI&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Sign in to your tenant
&lt;/h2&gt;

&lt;p&gt;When you have installed the Azure CLI you can sign in to your tenant. If you are on a dev-tenant or you don’t have a subscription to your account you should also add the “Allow-no-subscription” flag like shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;az&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;login&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;span class="n"&gt;az&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;login&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--allow-no-subscriptions&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Add the app
&lt;/h2&gt;

&lt;p&gt;When you have successfully signed in you can register a new app with a simple line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;az&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ad&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--display-name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;MyApp01&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--available-to-other-tenants&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return a JSON object with the app information. I have shortened it down a bit in the example below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"acceptMappedClaims"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"addIns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"allowGuestsSignIn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"allowPassthroughUsers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"appId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ee26ecb3-977f-4520-ac21-be9eec424538"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"oauth2RequirePostResponse"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"objectId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"301fc40c-a293-4509-8178-9d1b0fd76444"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two values that you should notice are the “appId, and the “objectId”. These values are often used when connecting to your registered app remotely. You can find the same information in the azure portal.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz539xeyujmjxk5siumqp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz539xeyujmjxk5siumqp.png" alt="Screenshot showing the app registration in Azure AD portal"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/en-us/cli/azure/ad/app?view=azure-cli-latest" rel="noopener noreferrer"&gt;List of Azure CLI – Azure AD app commands&lt;/a&gt; (Microsoft docs)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/en-us/cli/azure/?view=azure-cli-latest" rel="noopener noreferrer"&gt;Azure Command Line Interface documentation startpage&lt;/a&gt; (Microsoft docs)&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Did you find this article usefull? &lt;a href="https://twitter.com/acupof_dev" rel="noopener noreferrer"&gt;Follow me on twitter&lt;/a&gt; to be notified when I publish something new!&lt;/p&gt;

&lt;p&gt;Also, if you have any feedback or questions, please let me know in the comments below. :)&lt;/p&gt;

&lt;p&gt;Thank you for reading! &lt;/p&gt;

&lt;p&gt;/Eli&lt;/p&gt;

</description>
      <category>azure</category>
      <category>azurecli</category>
      <category>microsoft365</category>
      <category>microsoft</category>
    </item>
    <item>
      <title>Accessibility evaluation tools</title>
      <dc:creator>Eli H. Schei</dc:creator>
      <pubDate>Fri, 27 Aug 2021 06:12:53 +0000</pubDate>
      <link>https://dev.to/elischei/accessibility-evaluation-tools-4mbg</link>
      <guid>https://dev.to/elischei/accessibility-evaluation-tools-4mbg</guid>
      <description>&lt;p&gt;After learning about &lt;a href="https://dev.to/elischei/web-accessibility-for-developers-part-two-5-principles-you-can-start-implementing-now-1dm0"&gt;different accessibility principles&lt;/a&gt;, looking at &lt;a href="https://dev.to/elischei/a-look-at-some-more-complex-accessibility-challenges-lah"&gt;more complex challenges&lt;/a&gt;, and going &lt;a href="https://dev.to/elischei/a-deep-dive-into-aria-5071"&gt;in depth on ARIA&lt;/a&gt; we have finally arrived at the last part of this series. And it is time to talk (write) about accessibility evaluation tools. &lt;/p&gt;

&lt;p&gt;There are a lot of different tools to use for accessibility evaluation, in this post I will cover my personal preferences. If you know about an awesome tool I should try please let me know! &lt;/p&gt;

&lt;h2&gt;What are accessibility evaluation tools?&lt;/h2&gt;

&lt;p&gt;Like the name sugests accessibility evaluation tools are tools that help you evaluate how accessible a site is. These tools perform automated tests and gives you feedback on how accessible your site is according to the WCAG principles. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remember to think for yourself. &lt;/strong&gt;&lt;br&gt;These tools can be of great value, especially if you are new to accessibility. But it is important to remember to think for yourself as well. Focus on learning and understanding the different WCAG principles and how to implement them rather than relaying on tools only. &lt;/p&gt;

&lt;p&gt;I use these tools regularly but they are not a part of my everyday workflow. Typically I run one of them when I have finished a new feature - before deploying to test - to make sure I havn't missed anything. Or if I refacor a component and I'm afraid my changes might "break" something I run an evaluation to make sure the content is still accessible. &lt;/p&gt;

&lt;h2&gt;The tools I use&lt;/h2&gt;

&lt;p&gt;As I mentioned above there are a lot of different accessibility evaluation tools, and they mostly cover the same things. The decision of which tool to use often comes down to personal preference. &lt;/p&gt;

&lt;h3&gt;&lt;a href="https://chrome.google.com/webstore/detail/siteimprove-accessibility/efcfolpjihicnikpmhnmphjhhpiclljc/" rel="noreferrer noopener" title="https://chrome.google.com/webstore/detail/siteimprove-accessibility/efcfolpjihicnikpmhnmphjhhpiclljc/"&gt;Siteimprove&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felischei.com%2Fwp-content%2Fuploads%2F2021%2F08%2Fsiteimprove-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felischei.com%2Fwp-content%2Fuploads%2F2021%2F08%2Fsiteimprove-2.png" alt="Screen shot of SiteImprove tab that lists detected accessibility issues."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;br&gt;The Site Improve chrome extension gives you a button in your browser that will run an accessibility test on the page you are currently on. The results of the test shows up as a panel to the left in your browser window. It displays issues sorted into different categories and gives you details about what should be fixed - and also hints on how to fix it. &lt;/p&gt;

&lt;p&gt;I love siteimprove. It's easy to use, it gives you a quick overview - and also provides details if you need them. It gives you a lot of information about the different areas of accessibility.&lt;/p&gt;

&lt;h3&gt;&lt;a href="https://developers.google.com/web/tools/lighthouse/" rel="noreferrer noopener" title="https://developers.google.com/web/tools/lighthouse/"&gt;Lighthouse&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Lighthouse is available as its own tab in chrome devtools&lt;/p&gt;

&lt;p&gt;I mainly use Lighthouse to test the performance of a website (which is also an important part of accessibility - not everyone have access to a fast internet connection). But it will also give you an accessibility score and tell you what needs to be fixed. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felischei.com%2Fwp-content%2Fuploads%2F2021%2F08%2Flighthouse-accessibility-1024x441.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felischei.com%2Fwp-content%2Fuploads%2F2021%2F08%2Flighthouse-accessibility-1024x441.png" alt="Screen shot of LightHousetab that lists detected accessibility issues."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;&lt;a href="https://chrome.google.com/webstore/detail/axe-devtools-web-accessib/lhdoppojpmngadmnindnejefpokejbdd/" rel="noreferrer noopener" title="https://chrome.google.com/webstore/detail/axe-devtools-web-accessib/lhdoppojpmngadmnindnejefpokejbdd/"&gt;Axe dev tools&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Like lighthouse Axe dev tools has its own tab in devtools. You can scan the whole site, or only parts of it (requires you to log in). It presents a list of issues and possible solutions to fix them. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felischei.com%2Fwp-content%2Fuploads%2F2021%2F08%2FaxeDevTools-1024x398.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felischei.com%2Fwp-content%2Fuploads%2F2021%2F08%2FaxeDevTools-1024x398.png" alt="Screenshot of Axe Dev Tools tab that lists detected accessibility issues."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Tools for checking colors&lt;/h3&gt;

&lt;p&gt;There are a lot of different color checking tools out there. Some browsers also have their own built-in version in devtools. But the tools I use most are &lt;a href="https://webaim.org/resources/contrastchecker/" rel="noreferrer noopener" title="https://webaim.org/resources/contrastchecker/"&gt;WebAIM contrast checker&lt;/a&gt; and &lt;a href="https://contrastchecker.com/" rel="noreferrer noopener" title="https://contrastchecker.com/"&gt;contrastchecker.com&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;Other resources&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.w3.org/WAI/ER/tools/" rel="noreferrer noopener" title="https://www.w3.org/WAI/ER/tools/"&gt;List of accessibility tools&lt;/a&gt; (W3C)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://webaim.org/articles/tools/" rel="noreferrer noopener" title="https://webaim.org/articles/tools/"&gt;Introduction to accessibility tools&lt;/a&gt; (WebAIM)&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Did you find this article usefull? &lt;a href="https://twitter.com/acupof_dev" rel="noopener noreferrer"&gt;Follow me on twitter&lt;/a&gt; to be notified when I publish something new!&lt;/p&gt;

&lt;p&gt;Also, if you have any feedback or questions, please let me know in the comments below. :)&lt;/p&gt;

&lt;p&gt;Thank you for reading, and good luck with your accessibility evaluation!&lt;/p&gt;

&lt;p&gt;/Eli&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>tooling</category>
    </item>
    <item>
      <title>A list of useful git resources + cheat sheet</title>
      <dc:creator>Eli H. Schei</dc:creator>
      <pubDate>Wed, 04 Aug 2021 13:33:37 +0000</pubDate>
      <link>https://dev.to/elischei/a-list-of-useful-git-resources-cheat-sheet-2eli</link>
      <guid>https://dev.to/elischei/a-list-of-useful-git-resources-cheat-sheet-2eli</guid>
      <description>&lt;p&gt;I’ve been collecting a list of usefull resources to learn, and get better in useing, git. And I thought I would share it with you. I also created a cheat sheet with the commands I use the most. I keep both the list and the cheat sheet in a github repository – feel free to add to them if you know about some good resources that I havn’t mentioned here.&lt;/p&gt;

&lt;p&gt;I will try to keep this blogpost up to date, but you can &lt;a href="https://github.com/Eli-Schei/resource-sheets/tree/main/git"&gt;always find the newest version on github&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Note: Resources that cost money are marked with 💰. I’m not sponcored by any of these. These are resources I found usefull myself.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Websites&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://product.hubspot.com/blog/git-and-github-tutorial-for-beginners"&gt;An intro to git and github for beginners&lt;/a&gt; (Hubspot)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://chris.beams.io/posts/git-commit/"&gt;How to write a git commit message&lt;/a&gt; (Chris Beams)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/pragativerma18/confusing-terms-in-the-git-terminology-1578"&gt;Confusing terms in the git terminology&lt;/a&gt; (dev.to by Pragati Verma)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Books&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project#_commit_guidelines"&gt;Commit guidelines&lt;/a&gt; (git-scm.com book)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.packtpub.com/product/git-essentials/9781785287909"&gt;Git essentials&lt;/a&gt; (Ferdinando Santacroce) 💰&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Videos&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=USjZcfj8yxE"&gt;Learn Git In 15 minutes&lt;/a&gt; (Colt Steele)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=nhNq2kIvi9s"&gt;Learn GitHub in 15 minutes&lt;/a&gt; (Colt Steele)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Podcasts&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://open.spotify.com/episode/3E9rAq4OUO5KNH9dEFVony?si=8LiF43NqSHOWsF05sE4hnQ"&gt;git fundamentals&lt;/a&gt; (Syntax fm)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://open.spotify.com/episode/0Sxv86yBWWA9RJRisMUj7C?si=4XnZkeYIR66PdX3vl5EhGw"&gt;git rebase explained&lt;/a&gt; (Syntax fm)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.ladybug.dev/episodes/git-and-github"&gt;git and github&lt;/a&gt; (Ladybug podcast)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cheat Sheet
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dMME0_A5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ne3nqq3szxg52befu9tq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dMME0_A5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ne3nqq3szxg52befu9tq.jpg" alt="A git cheat sheet that shows my most used git commands"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://elischei.com/wp-content/uploads/2021/06/git-cheat-sheet-large-scaled.jpg"&gt;Click here for the image in full size&lt;/a&gt;. Or here for &lt;a href="https://github.com/Eli-Schei/resource-sheets/blob/main/git/git-cheat-scheet.md"&gt;the markdown version&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>git</category>
      <category>sourcecontrol</category>
      <category>cheatsheet</category>
    </item>
    <item>
      <title>A deep dive into ARIA</title>
      <dc:creator>Eli H. Schei</dc:creator>
      <pubDate>Mon, 12 Jul 2021 10:45:09 +0000</pubDate>
      <link>https://dev.to/elischei/a-deep-dive-into-aria-5071</link>
      <guid>https://dev.to/elischei/a-deep-dive-into-aria-5071</guid>
      <description>&lt;p&gt;Have you heard about ARIA attributes but don’t really understand what they are, or how to use them? Or maybe you know the basics but wan’t to deepen your understanding on the topic? Either way you are in the right place! In this blogpost I will cover what ARIA is, why and when you should use them. I will also go into ARIA roles in debth, and ARIA states and properties.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prerequesites: I will assume you have some basic understandig of accessibility concepts, if you don’t I recommend to read “Part 1: Introduction” before diving into this blog post.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What is ARIA?
&lt;/h2&gt;

&lt;p&gt;I briefly covered this in “Part 1: Introduction” but thught I should include it here as well.&lt;/p&gt;

&lt;p&gt;The MDN Web Docs defines ARIA like this: “Accessible Rich Internet Applications (ARIA)is a set of attributes that define ways to make web content and web applications (especially those developed with JavaScript) more accessible to people with disabilities.”&lt;/p&gt;

&lt;p&gt;If a screen reader can’t understand the semantics of your web site content – your site is unaccessible to those who use that kind of assistive technology. This is where ARIA comes in – by adding ARIA attributes to your HTML elements the screen reader can get the context and descriptive details. ARIA attributes have no effect on how the HTML elements are visually presented.&lt;/p&gt;

&lt;h3&gt;
  
  
  Different types of ARIA
&lt;/h3&gt;

&lt;p&gt;ARIA attributes is a common name for two main categories: “ARIA roles” and “ARIA states and properties”. While ARIA roles describes the type of user interface an HTML element represents, ARIA state and properties describes the current state of the element, and are likely to change as the user interacts with the application. In the next sections we will take a closer look at both roles, and states and properies.&lt;/p&gt;

&lt;h3&gt;
  
  
  When should you use ARIA?
&lt;/h3&gt;

&lt;p&gt;ARIA are supposed to be a supplement to your HTML. If should focus on making a logical site structure, using semantic HTML elements and giving things descriptive names. Adding ARIA attributes should be a last resort.&lt;/p&gt;

&lt;p&gt;That being said, it mostly applies to the use of ARIA roles – since thats quite similar to semantic HTML. ARIA states and properties on the other hand can be used with both semantic or non semantic HTML elements to give the user even more information.&lt;/p&gt;

&lt;h2&gt;
  
  
  ARIA Roles
&lt;/h2&gt;

&lt;p&gt;There are a lot of different ARIA roles and they are divided into six categories. In general they all describe different types of user interfaces.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Widget roles&lt;/strong&gt;&lt;br&gt;
Describes interactive components like “button”, “progressbar” or “tablist” (++). Should only be used where there are no semantic HTML elements to match, or if the semantic element is not supported in a commonly used browser.&lt;br&gt;
Use &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; instead of &lt;code&gt;&amp;lt;div role="button"&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Composite roles&lt;/strong&gt;&lt;br&gt;
These roles are typically “parent roles” of widget roles. Like “radiogroup” is the parent of widget-role “radio“.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Document structure roles&lt;/strong&gt;&lt;br&gt;
Used to describe the structure of a webpage. Like the other roles these should also only be used if there is no semantic element that can be used instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Landmark roles&lt;/strong&gt;&lt;br&gt;
These roles also describes the site structure, but from a higher level. Landmark roles include, but are not limited to, “banner”, “main” and “navigation”.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Live region roles&lt;/strong&gt;&lt;br&gt;
Used to describe what type of live content can be expected. Includes attributes for “alert”, “timer” and “status”.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Window roles&lt;/strong&gt;&lt;br&gt;
There are two window roles “dialog” and “alertdialog”. These are used on content that are ment to be displayed as a sub-window, or modal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.w3.org/TR/wai-aria/#role_definitions"&gt;You can find a full overview of the different roles on the W3 recommendations site&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  How to use ARIA roles
&lt;/h3&gt;

&lt;p&gt;Like I mentioned previously you should strive to use the correct semantic elements and only add ARIA to add extra context or information. Lets look at some examples.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;//using ARIA role
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"banner"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   This is the header area of my website
   &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"logo.jpg"&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;

//using semantic HTML
&lt;span class="nt"&gt;&amp;lt;header&amp;gt;&lt;/span&gt;
   This is the header area of my website
   &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"logo.jpg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example I use the role “banner” to indicate that this is the main header area of the website. And that this area will contain information such as navigation links, logo etc. But there are also a semantic HTML element that will indicate the same role, .&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Always exceptions&lt;/strong&gt;
In most cases you want to go with the semantic HTML, but in some special instances you might need to use the role attribute instead. One example of this is if you work on a project with a lot of legacy code and you don’t have the budget to refactor it. Then a quick fix to make it more accessible would be to add the role=”banner”. Or if you have no access to the html you can add the role=”banner” using javascript.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And not every user interface has a corresponding semantic element, and then we can use ARIA roles to make the element accessible. Lets look at an example using a “tablist”.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"tablist"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"tab"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; TAB 1&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"tab"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;TAB 2&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"tabpanel"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;My first tab&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"tabpanel"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;My second tab&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;In the above example you can se that I have given the first &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;a role="tablist". And inside it are two buttons that both have a role="tab". Without these roles it would be impossible for assisitve technology to understand this part of the website.&lt;/p&gt;

&lt;p&gt;The elements with the role="tab" controls the visibility of an accosiated elemented with the role="tabpanel". We will take a closer look at how these relationships are configured in the next section about state and properties.&lt;/p&gt;

&lt;h2&gt;
  
  
  ARIA States and properties
&lt;/h2&gt;

&lt;p&gt;The other category of ARIA attributes are “states and properties”. These will sometimes change as the user interacts with the application. When changes occures the assistive technology is notified and can convey the information to the user.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Difference between state and properties&lt;/strong&gt;&lt;br&gt;
The difference is subtle and it’s not really important either. But you can think of it like this: a state is likely to change during user interaction, and a property is less likely to change. Lets look at some examples.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;aria-checked. Is likely to change if the user selects or unselects a checkbox. So this is a state.&lt;/li&gt;
&lt;li&gt;aria-requiered. The value of this is less likely to change as the user interacts with the site. So this is a property.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ARIA states and properties are divided into four categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Widget attributes – receive user input and process user actions.&lt;/li&gt;
&lt;li&gt;Live region attributes – indicates that content changes may occur without the element having focus.&lt;/li&gt;
&lt;li&gt;Drag and drop attributes&lt;/li&gt;
&lt;li&gt;Relationship attributes – indicate relationships or associations between elements which cannot be easaly determined from the document structure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lets continue with our tablist example and add some state and properties to it as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"tablist"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"tab"&lt;/span&gt; 
            &lt;span class="na"&gt;aria-selected=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; 
            &lt;span class="na"&gt;aria-controls=&lt;/span&gt;&lt;span class="s"&gt;"tab-1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
              TAB 1
    &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"tab"&lt;/span&gt; 
            &lt;span class="na"&gt;aria-selected=&lt;/span&gt;&lt;span class="s"&gt;"false "&lt;/span&gt; 
            &lt;span class="na"&gt;aria-controls=&lt;/span&gt;&lt;span class="s"&gt;"tab-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
              TAB 2
    &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"tabpanel"&lt;/span&gt; &lt;span class="na"&gt;aria-labelledby=&lt;/span&gt;&lt;span class="s"&gt;"tab1"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"tab-1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;My first tab&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"tabpanel"&lt;/span&gt; &lt;span class="na"&gt;aria-labelledby=&lt;/span&gt;&lt;span class="s"&gt;"tab2"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"tab-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;My second tab&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;Above you can see that we have added the attributes “aria-selected” and “aria-controls” to the button elements. aria-selected is in the category ‘widget attributes¨’, and it can have the value true or false. It describes wich of the elements that are currently selected. The other attribute “aria-controls” is a relationship attribute and tells us to wich of the tabpanels the button is connected.&lt;/p&gt;

&lt;p&gt;Another example of a relationship attribute is “aria-describedby” where the value points to the ID of the elements that describes the current element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;aria-describedby=&lt;/span&gt;&lt;span class="s"&gt;"openDialogInfo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Open dialog&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"openDialogInfo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    This will open the form in a dialog. All changes you have allready made will be lost.
&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;&lt;strong&gt;Aria-label vs aria-labeledby&lt;/strong&gt;&lt;br&gt;
Aria-label defines a string that labels the current element. Only use this if there is no visual label. If there is a visual label use that and add the “aria-labeledby” attribute instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using ARIA state and properties to give feedback on user interaction
&lt;/h3&gt;

&lt;p&gt;Its important to give the user updated info about the result of their interactions. As I mentioned previosuly – if states or properties change the assistive technology is notified and can tell the user what changed. Lets look at some of the attributes that can be used to provide information as the user interacts with your website.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;aria-invalid. Tells the user if their input is valid. This has four different states:
false – which means no errors are detected.
grammar – which means grammatical error
spelling – which means a spelling error is detected
true – which means the input is invalid&lt;/li&gt;
&lt;li&gt;aria-valuemin, aria-valuemax, aria-valuenow. These attributes are used to tell the user the min, max and current value of an element. The min and max values will stay the same but the valuenow will update based on user input.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To keep this post from getting any longer I will stop here. But there are a lot more attributes and its a good idea to familiarize yourself with them so you know what to reach for to make different interactions accessible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.w3.org/TR/wai-aria/#state_prop_taxonomy"&gt;You can find a full list of the different states and properties here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.w3.org/TR/wai-aria/"&gt;Accessible Rich Internet Applications&lt;/a&gt; (WAI-ARIA) 1.1 (W3C Recommendations)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.w3.org/TR/wai-aria/#usage"&gt;Using WAI ARIA&lt;/a&gt; (W3 Recommendations)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.w3.org/TR/wai-aria/#role_definitions"&gt;List of roles&lt;/a&gt; (W3 Recommendations)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.w3.org/TR/wai-aria/#state_prop_taxonomy"&gt;List of states and properties&lt;/a&gt; (W3 Recommendations)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques"&gt;ARIA techniques&lt;/a&gt; (MDN Web docs)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles"&gt;ARIA roles&lt;/a&gt; (MDN Web docs&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.a11yproject.com/posts/2014-05-15-getting-started-aria/"&gt;Getting started with ARIA&lt;/a&gt; (The a11y project)&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Did you find this article usefull? &lt;a href="https://twitter.com/acupof_dev"&gt;Follow me on twitter&lt;/a&gt; to be notified when I publish something new!&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>aria</category>
      <category>html</category>
    </item>
    <item>
      <title>5 must have extensions when working with SharePoint framework (SPfx)</title>
      <dc:creator>Eli H. Schei</dc:creator>
      <pubDate>Wed, 30 Jun 2021 11:20:53 +0000</pubDate>
      <link>https://dev.to/elischei/5-must-have-extensions-when-working-with-sharepoint-framework-spfx-5ag8</link>
      <guid>https://dev.to/elischei/5-must-have-extensions-when-working-with-sharepoint-framework-spfx-5ag8</guid>
      <description>&lt;p&gt;I have&lt;a href="https://dev.to/elischei/my-top-5-favorite-vscode-extensions-203d" title="My top 5 favorite VSCode extensions" rel="noreferrer noopener"&gt; previosly written a blogpost about my favorite extensions for VSCode&lt;/a&gt;. Today I want to share my favorite SPfx-specific extensions and tools. If you know about some extension, tool or package that should be on this list let me know! &lt;/p&gt;

&lt;h2&gt;1. &lt;a href="https://github.com/s-KaiNet/spfx-fast-serve" rel="noreferrer noopener" title="https://github.com/s-KaiNet/spfx-fast-serve"&gt;SPfx fast-serve &lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Do you feel like it takes forever to serve your project on the local server? And that the hot reaload is not exactly hot? Then you should try SPfx fast serve! &lt;a href="https://www.linkedin.com/pulse/enjoy-sharepoint-framework-development-denis-molodtsov/" rel="noreferrer noopener" title="https://www.linkedin.com/pulse/enjoy-sharepoint-framework-development-denis-molodtsov/"&gt;This article describes it in more detail and also covers the setup&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;2. &lt;a href="https://marketplace.visualstudio.com/items?itemName=eliostruyf.spfx-snippets" rel="noreferrer noopener" title="https://marketplace.visualstudio.com/items?itemName=eliostruyf.spfx-snippets"&gt;SPfx snippets &lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A nice little collection of snippets so you don't have to write everything from scratch. &lt;/p&gt;

&lt;h2&gt;3. &lt;a href="https://marketplace.visualstudio.com/items?itemName=eliostruyf.spfx-debug" rel="noreferrer noopener" title="https://marketplace.visualstudio.com/items?itemName=eliostruyf.spfx-debug"&gt;SPfx debug extension&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;For easier debugging. This is by the same creator as SPfx snippets, Elio Struyf ( &lt;a class="mentioned-user" href="https://dev.to/estruyf"&gt;@estruyf&lt;/a&gt; ) , &lt;a href="https://marketplace.visualstudio.com/publishers/eliostruyf" rel="noreferrer noopener" title="https://marketplace.visualstudio.com/publishers/eliostruyf"&gt;you should check out all of his extensions for SPfx and MS graph&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;4. &lt;a href="https://marketplace.visualstudio.com/items?itemName=RencoreGmbH.vscode-spfx-deploy-package" rel="noreferrer noopener" title="https://marketplace.visualstudio.com/items?itemName=RencoreGmbH.vscode-spfx-deploy-package"&gt;Rencore Deploy packages extension&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I usally prefer to &lt;a href="https://elischei.com/deploy-your-spfx-solution-using-pnp-powershell/" rel="noreferrer noopener" title="How to deploy your SPfx solution using PnP powershell"&gt;deploy my spfx apps using pnp powershell,&lt;/a&gt; but if you want to do it directly from VSCode this extension is for you. &lt;/p&gt;

&lt;h2&gt;5. &lt;a href="https://dev.to/elischei/how-to-use-node-version-manager-nvm-for-windows-to-handle-different-node-versions-5a35" rel="noreferrer noopener" title="https://elischei.com/how-to-use-nvm-for-windows/"&gt;Use NVM to switch between node versions&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;If you work with multiple apps that have different node dependencies Node Version Manager (NVM) is a must. I have previously &lt;a href="https://dev.to/elischei/how-to-use-node-version-manager-nvm-for-windows-to-handle-different-node-versions-5a35" rel="noreferrer noopener" title="How to use node version manager (nvm for windows) to handle different node-versions"&gt;written a blogpost on how to setup and use NVM (for windows)&lt;/a&gt;. &lt;/p&gt;




&lt;p&gt;Did you find this article usefull? &lt;a href="https://twitter.com/acupof_dev" rel="noreferrer noopener"&gt;Follow me on twitter&lt;/a&gt; to be notified when I publish something new!&lt;/p&gt;

&lt;p&gt;Also, if you have any feedback or questions, please let me know in the comments below. :) &lt;/p&gt;

&lt;p&gt;Thank you for reading, and happy coding!&lt;/p&gt;

&lt;p&gt;/Eli&lt;/p&gt;

</description>
      <category>spfx</category>
      <category>extensions</category>
      <category>vscode</category>
    </item>
  </channel>
</rss>
