Conditional Rendering

Sometimes, you may only want the Tether widget to be visible to certain individuals, team members, or stakeholders. There are various ways to accomplish this. One method is by using Event Hooks to dispatch a tether.show event when certain conditions are met. Another method, which we will describe here, is to conditionally render your Tether script tag. This offers an advantage of Event Hooks as when conditionally rendering the entire script tag, Tether's javascript code will not be loaded or executed at all. Thereby reducing overhead and access for users that don't need it.

Conditional rendering is not an explicit feature provided by Tether, but rather is a property of the script tag used to mount Tether onto your web app when used in tandem with server-side rendering, dynamic frameworks like React or Vue, or templating engines like Blade. The specifics of how you will need to implement conditional rendering vary depending on what condition should dictate Tether's visibility, as well as what development tools you use. In this article, I'll cover a few common implementations of conditional rendering.


Example 1 - HTML & Javascript

While plain HTML doesn't natively support conditional rendering, you can still implement it using vanilla Javascript.

<html>
    <head>
        <script>
            window.addEventListener('DOMContentLoaded', function() {
                var tetherScript = document.createElement('script');
                tetherScript.defer = true;
                tetherScript.src = 'https://app.tethered.dev/js/tether.js';
                tetherScript.setAttribute('data-id', 'tether-client');
                tetherScript.setAttribute('data-token', '*********************');
                tetherScript.setAttribute('data-project-uuid', '*********************');

                // This condition assumes the existence of a global user object. Customize this condition as needed to suit your environment.
                if (window.user.role === 'ADMIN') {
                    document.head.appendChild(tetherScript);
                }
            });
        </script>
    </head>
</html>

Example 2 - Blade

If you're using Laravel's Blade templating engine, you can use the @if Blade directive to conditionally render the Tether script tag.

<html>
    <head>
        ...
        @if(env('APP_ENV') !== 'production')
        <script
            defer
            type="text/javascript"
            src="app.tethered.dev/js/tether.js"
            data-id="tether-client"
            data-token="************************"
            data-project-uuid="************************"
        ></script>
        @endif
    </head>
    ...
</html>

Example 3 - React

Once again, there are many ways to implement conditional rendering in React. You can use an inline ternary expression or directly append the script tag to the DOM using javascript, among others. In this example, I'll demonstrate a few different ways you might represent your condition and render the Tether script tag.

Using inline ternary expressions


import React from 'react';

// The authenticated user object could be passed as a prop, retrieved from global state, extracted from session, etc.
const ConditionalRenderingExample = ({ loggedInUser }) => {
    return (
        <>
            {
                // In this example, the user object has a specific property that determines whether the user is an admin
                loggedInUser.isAdmin
                    ? <script 
                        defer 
                        src="https://app.tethered.dev/js/tether.js" 
                        data-id="tether-client" 
                        data-token="*********************" 
                        data-project-uuid="*********************"
                    ></script>
                    : null
            }
        </>
    );
};

export default ConditionalRenderingExample;


import React from 'react';

const ConditionalRenderingExample = (props) => {
    // An array of emails can also be used to identify admins. Can be declared in-component, passed as a prop, or declared as a global variable or state
    const adminEmails = [
        'john@example.com',
        'admin1@example.com',
        'admin2@example.com',
    ];

    return (
        <>
            {
                // If the user object doesn't have a specific property that indicates their privilege level, you can instead check if their email address exists in a hard-coded list of admin emails
                adminEmails.includes(loggedInUser.email)
                    ? <script
                        defer
                        src="https://app.tethered.dev/js/tether.js"
                        data-id="tether-client"
                        data-token="*********************"
                        data-project-uuid="*********************"
                    ></script>
                    : null
            }
        </>
    );
};

export default ConditionalRenderingExample;


Using React hooks

import React from 'react';

const ConditionalRenderingExample = ({ user }) => {
    useEffect(() => {
        const tetherScript = document.createElement('script');
        tetherScript.defer = true;
        tetherScript.src = 'https://app.tethered.dev/js/tether.js';
        tetherScript.setAttribute('data-id', 'tether-client');
        tetherScript.setAttribute('data-token', '*********************');
        tetherScript.setAttribute('data-project-uuid', '*********************');

        if (user.role === 'ADMIN') {
            document.head.appendChild(tetherScript);
        }
    }, [user.id]);

    return (
        <div>
            ...
        </div>
    );
};

export default ConditionalRenderingExample;

Example 4 - Vue

Our Vue implementation is very similar to React, but with a slightly different syntax which relies on inline directives instead of JSX

<template>
    <script
        v-if="user.role === 'ADMIN'"
        defer
        src="https://app.tethered.dev/js/tether.js"
        data-id="tether-client"
        data-token="*********************"
        data-project-uuid="*********************"
    ></script>
</template>

<script>
export default {
    props: {
        user: {
            type: Object,
            required: true,
        },
    },
}
</script>