Meteor
Posted By Sebastian

Meteor & Svelte – Building Full-Stack Reactive Web Applications – 06: User Accounts


Subscribe On YouTube

Episodes

Meteor makes user management very easy. You can quickly add a full-featured user management system into your application which lets the user create user accounts and authenticate. In this episode we’ll extend the sample application and add user management features to our Svelte front-end application.

We’ll then extend our application, and make use of the user system. E.g. we’ll make sure that certain functionality (like create new issues, delete issues) is only available when the user is authenticated logged in.

Installing Additional Meteor Packages

First of all we need to make sure to install further Meteor packages:

$ meteor add accounts-ui accounts-password

The accounts-ui and the accounts-password package provides us with functionality and UI widgets which can easily be used to integrate a user accounts system in our application.

The UI widgets are provided as Blaze templates. This means that we need to find a way of how to embed Blaze template in our Svelte components. Luckily there is another packages which is providing an easy way to achieve that:

$ meteor add svelte:blaze-integration

Using The loginButton Template In The Svelte Application

Now that we’ve installed all packages which are needed we’re including the loginButton template in our Svelte app next. This template includes the widgets which comes from the accounts-ui package and which enables the user to create a new account, manage an existing account and login.

Add the following import statement in App.js:

import { BlazeTemplate } from 'meteor/svelte:blaze-integration';

Now we can make use of the BlazeTemplate element to include the loginButtons template in our Svelte template code like you can see in the following:

<BlazeTemplate template="loginButtons" />

In addition we’re able to also include a navigation bar on top and embed the loginButtons template in the navigation bar:

        <nav>
            <a href="#" class="brand">Meteor & Svelte Issue List App</a>

            <div class="menu">
                <BlazeTemplate template="loginButtons" data={{align: 'right'}}/>    
            </div>
        </nav>

Configuring The Accounts Package

By default each user accounts is build up from an email address and password. Instead of using the email address as the login name I’d like to change to a username which can be chosen freely. Therefore we need to include an additional configuration file in imports/startup/. Inside that folder create a new file accounts-config.js and insert the following lines of code:

import { Accounts } from 'meteor/accounts-base';

Accounts.ui.config({
    passwordSignupFields: 'USERNAME_ONLY'
});

To activate that configuration we also need to make sure that the configuration is imported in the client application. We do that in client/main.js by adding the following statement on top:

import '../imports/startup/accounts-config.js';

Storing User Information

Now that everything is configured we can start to use the accounts functionality in our app. The first thing we add is the storage of the current user information together with the issue dataset.

In App.svelte add the following import statement:

import { Meteor } from 'meteor/meteor';

Then create a reactive variable with the name currentUser in App component in the following way:

$: currentUser = useTracker(() => Meteor.user());

Therewith we’re making sure that we have access to the current username at any point in time.

To store the user information for each issue we’re extending the issue object which is inserted into the collection by two properties: userId and userName:

    function handleSubmit(event) {
        Issues.insert({
            title: newIssue.title,
            description: newIssue.description,
            dueDate: newIssue.dueDate,
            priority: newIssue.priority,
            userId: Meteor.userId(),
            userName: Meteor.user().username
        });

The userId value is set by using the Meteor.userId() method and the user name is set by using Meteor.user().username.

Conditional Output

Based on the information if a logged in user is available (via $currentUser) we’re now able decide which things to output. E.g. the form to create new issues should only be available if a user is logged in, so we embed it in a {#if $currentUser} … {/if} block like you can see in the following listing:

        {#if $currentUser}
        <form style="padding-top: 75px" on:submit|preventDefault={handleSubmit}>
            <label for="title">Title: </label>
            <input  id="title"
                    type="text"
                    bind:value={newIssue.title}
                    />
            <label for="description">Description: </label>
            <input  id="description"
                    type="text"
                    bind:value={newIssue.description}
                    />
            <label for="dueDate">Due Date: </label>
            <input  id="dueDate"
                    type="text"
                    bind:value={newIssue.dueDate}
                    />
            <label for="priority">Priority:</label>
            <select id="priority" bind:value={newIssue.priority}>
                <option value="Low">Low</option>
                <option value="Medium">Medium</option>
                <option value="High">High</option>
            </select>
            <input type="submit">
        </form>
        {/if}

In the same way we’re making sure that in case of a logged in user another column is added to the table output, so that this column then can contain the delete button:

        <table>
            <tr>
                <th>Title</th>
                <th>Description</th>
                <th>Due Date</th>
                <th>Priority</th>
                <th>Username</th>
                {#if $currentUser}<th></th>{/if}
            </tr>
            {#each $issues as issue}
                <Issue issue={issue} />
            {/each}
        </table>   

In Issue.svelte we’re only outputting the delete button if a user is logged in:

<script>
    import { Meteor } from 'meteor/meteor';
    import { useTracker } from 'meteor/rdb:svelte-meteor-data';
    import { Issues } from "../api/issues.js";

    export let issue;

    $: currentUser = useTracker(() => Meteor.user());

    function deleteIssue() {
        Issues.remove(issue._id);
    }
</script>

<tr>
    <td>{issue.title}</td>
    <td>{issue.description}</td>
    <td>{issue.dueDate}</td>
    <td>{issue.priority}</td>
    <td>{issue.userName}</td>
    {#if $currentUser}
        <td><button class='error' on:click={deleteIssue}>Delete</button></td>
    {/if}
</tr>

Advertisement: Svelte.js - The Complete Guide

Build high-performance web applications with Svelte.js – a lightweight JavaScript compiler:

Svelte.js – The Complete Guide*

  • Svelte.js from scratch, with zero knowledge assumed
  • All the theory and practical applications of Svelte
  • Core concepts and advanced techniques to build Svelte applications

Go To Course*

* Affiliate Link / Advertisement: This blog post contains affiliate links, which means that if you click on one of the product links and buy a product, we’ll receive a small commission. There are no additional costs for you. This helps support the channel and allows us to continue to make videos like this. Thank you for the support!


Using and writing about best practices and latest technologies in web design & development is my passion.