deactivating a form field using a function in Next.js

Here's the scenario: I have an input slider that needs to be disabled based on the role requirements of the logged-in user. For instance, if the input is only accessible to users with an accountant level role, then it should be disabled for those who don't have that specific role. The input will still be visible, but I want it to be disabled.

The usual approach would be something like

disabled={!loggedInUser.isAccountant}
, which usually suffices. However, there are cases where multiple roles should be able to access the input, even if the user doesn't possess all of them. For example, I might want both an accountant and an admin to access the input, but not a partner, while still keeping the field viewable.

I attempted to create a function that takes the user's document and checks if any key matches a specified role passed in. If a role-key match is found and the corresponding value is true, the user has the necessary role(s) to access the input. Unfortunately, no matter what I do, the function always returns a Promise<Pending> when inserted into the disabled prop of the component.

Below is an example of the input:

<Form.Group className={styles.boolean} controlId="isPaid">
            {/* True/False */}
            <Form.Check
              type="switch"
              id="custom-switch"
              label="Is Paid User"
              checked={formData.isPaidUser}
              onChange={(e) =>
                setFormData({
                  ...formData,
                  isPaidUser: !formData.isPaidUser,
                })
              }
              // Problem is here!
              disabled={checkRole(loggedInUser, ['isAdmin', 'isAccountant']}
            ></Form.Check>
          </Form.Group>

And here's the checkRole function:

/**
 * @description Check if the user has the role passed in the array, passing in multiple roles will check if the user has any of the roles
 * @param {Object} user - The logged in user object
 * @param {Array} roles - The roles to check against
 * @returns {Boolean} - Returns true if the user has the role, false if not
 * @example checkrole({user}, ['isAdmin'])
 * @example checkrole({user}, ['isAdmin', 'isPartner'])
 *
 * @author   Austin Howard
 * @version  1.0.1
 * @since    1.0.0
 * 
 */
export default async (user, roles) => {
  if (!user) return false;
  let hasRole = false;
  await Object.keys(user).forEach((key) => {
    console.log(`key: ${key}`);
    if (roles.includes(key)) {
      console.log(`user[key]: ${user[key]}`);
      if (user[key]) {
        console.log(`setting hasRole to true`);
        hasRole = true;
      }
    }
  });
  return hasRole;
};

I've experimented with different ways of calling the function, including setting up a self-calling async function to wrap the checkRole function. However, despite these efforts, I haven't been able to get the boolean result I need correctly.

Answer №1

This code snippet does not appear to be for an asynchronous operation, perhaps switching to a synchronous approach like the following function would be more suitable:

function checkUserRole(user, roles){
  return roles.some(role => user[role]);
}

Answer №2

After some experimentation, I managed to get this working by utilizing the useState and useEffect hooks. These are used by the form input to determine whether it should be disabled or not.

Here is how the code snippet looks:

const Form = () => {
    const [disableFormInput, setDisableFormInput] = React.useState(false); // Initial state
React.useEffect(() => {
    if (user) {
      // Set up a self-invoking function to check if the user has the required roles
      (async () => {
        setCanDelete(await checkRole(loggedInUser, ['isAdmin']));
      })();
    }
}, [user]);
...,
// The input will be disabled based on the value of disableFormInput
<input disabled={!disableFormInput} ... />  

Answer №3

After collaborating with a coworker, I have come across a more efficient solution that requires less code and is highly scalable. While my initial answer was functional, it felt a bit like a workaround. Here is an improved approach:

Instead of setting booleans for each role a user has on the front end, we can simplify the process by using Regex testing on the string value of the user's roles. For instance, if a user has roles such as "admin accountant partner" in their role field within the loggedInUser object, we can easily check if they have the required roles using Regex testing.

The updated solution is as follows:

<input disabled={!/accountant|admin|partner/.test(loggedInUser.role)} ... />

This method will significantly improve scalability compared to my initial response.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Finding the index of an element in an array using the filter method in Angular JavaScript

As I was working with an array of pages in a book, I wanted to find the index of a specific page that had been identified using filter. While my current function gets the job done, I can't help but wonder if there's a way to combine indexOf or fi ...

The ng-isolate-scope is not properly connected to the specified templateUrl

I am encountering difficulties when trying to implement isolated scope with templateUrl. Here is my directive test: beforeEach(ngModule('app.directives')); var scope, compile beforeEach(inject(function($rootScope, $compile){ scope = $ro ...

jQuery mobile collapsed list view is not functioning correctly when used with search feature

I have successfully implemented a listview in jquery with a listdivider that includes a filter function. The search feature works perfectly, however, when collapsing either of the list dividers, the search functionality stops working altogether. <!DOCT ...

Yeoman - Storing global settings efficiently

I have recently developed a Yeoman generator and am now looking to incorporate prompts for certain global configurations. My goal is to have the generator prompt users for their GitHub username and token during the initial run, and then somehow store this ...

Having trouble combining different styles with Material-ui and Radium?

Trying to integrate Radium with Material-ui has presented a challenge. Attempting to apply multiple styles to a single Material-ui component results in no styling being applied. For instance, the following code fails to render any styling: <MenuItem st ...

Bug Alert: Incompatibility between Angular $resource and PHP causing issues with Update and Delete functionalities

As a newcomer to both AngularJS and PHP, I have been struggling to find comprehensive documentation on using $resource to update records in a database. While I did come across a helpful tutorial here that covers most aspects of $resource usage, I am having ...

Is it necessary to use Hapi.js on the client side in order to establish a websocket connection using the Hapi.js protocol?

Currently, I am in the process of developing an API using Hapi and requiring WebSocket functionality. After some research, it appears that Nes is the preferred choice to integrate with Hapi for this purpose. Fortunately, Nes simplifies the process signific ...

Is there a way to conceal JavaScript code?

I am trying to keep my AJAX code hidden from users who view the source of my PHP page. How can I achieve this? Below is the AJAX code that I currently have: <script type="text/javascript"> function Ajax(){ var xmlHttp; try{ xmlHttp=n ...

Is the Javascript file successfully loaded?

Is there a way to verify if all 8 javascript files are loaded in an html document and handle any errors that may occur if one of the files fails to load, across various browsers? Thank you for your help! ...

I'm looking for a streamlined method to simultaneously access multiple APIs with GraphQL and React

For my client side project, I'm using GraphQL and React but opting not to use Redux for state management. Instead, I have organized my API calls into custom hook files as shown below: const [getSomeData, { data: getSomeDataData, loading: getSomeData ...

Unexpected Timed Out error from Socket.IO adapter when MongoDB connection is lost

I have been experimenting with capturing the disconnection event in mongodb. Everything is working smoothly with this setup: simple.js 'use strict'; var mongoose = require('mongoose'); mongoose.connect('mongodb://localhost:2701 ...

Tips for integrating custom images or icons into Onsen-UI:

I am currently utilizing the Onsen-UI framework along with AngularJS to create a mobile application. I want to incorporate custom images for buttons, but they appear blurry or unclear on certain mobile devices when the app is launched. Below is my code sn ...

Using getInitialProps in _app will override the getInitialProps implementation in other pages

Recently diving into Nextjs, I've been facing an issue with getInitialProps in _app.js. My goal is to utilize this function to secure routes and retrieve user information for logged-in users. However, when attempting to use getInitialProps in other pa ...

Use jQuery to swap out two div classes within a table cell (TD) if they are

Although I'm making progress, I must confess that jQuery and CSS are not my strong suits. The objective: To create a dynamic div within a table data cell for a calendar feature. The content of the div varies based on the date range input. A filled d ...

Close button for body

I have created a form that floats in the center of the screen On this form, I have included a button designed to close it However, I would like for the form to be closed anywhere on the screen when clicked with the mouse Here is my code: $(".offer-clo ...

Retrieve data upon component mounting and deactivate the query in React-query

When navigating to a search result page, query parameters are passed to useQuery. I want the data to be fetched only when the user clicks the "Search" button after changing the search prompt. I attempted to use enabled: false and call refetch() on button ...

The attribute "value" for Material-UI autocomplete cannot be used in conjunction with the "getOptionLabel" attribute

<Autocomplete id="license-select" options={licReqList} value = {licReqList[0] ? licReqList[0].licReqStr : null} getOptionLabel={(option) => option.licReqStr} onChange={ha ...

Can you explain the process of retrieving API information from a component directory with Next.js?

In the components folder, I have created a reusable component that displays user details for those who log into the system in the header section. Currently, I am attempting to utilize getInitialProps with isomorphic-unfetch. static async getInitialProps( ...

Problem with Chrome Compatibility for Bootstrap Carousel

My webpage features a carousel implemented as a slider. It seems to be working fine in Firefox and mobile browsers, except for Chrome where it doesn't show up at all. I can't seem to figure out what's causing the issue. Here is the syntax I& ...

Typescript indicates that an object may be potentially null

I've hit a roadblock where I keep getting warnings that the objects might be null. After searching online and on StackOverflow, I've tried numerous solutions with no luck. My goal is to insert the text "test" into the HTML elements using their ID ...