Organization membership requests
These methods on the Organization
object allow you to manage the membership requests for an organization.
The following examples assume:
- you have followed the quickstart in order to add Clerk to your JavaScript application
- you have enabled the Organizations feature in your Clerk Dashboard
- you have enabled Verified domains and Automatic suggestion for your organization
getMembershipRequests()
Retrieve the list of membership requests for the currently active organization.
function getMembershipRequests: (params?: GetMembershipRequestParams) => Promise<ClerkPaginatedResponse<OrganizationMembershipRequestResource>>;
GetMembershipRequestParams
Name | Type | Description |
---|---|---|
initialPage? | number | A number that can be used to skip the first n-1 pages. For example, if initialPage is set to 10, it is will skip the first 9 pages and will fetch the 10th page. |
pageSize? | number | A number that indicates the maximum number of results that should be returned for a specific page. |
status? | string | The status of the membership requests that will be included in the response. |
getMembershipRequests()
returns
Type | Description |
---|---|
Promise<ClerkPaginatedResponse<OrganizationMembershipRequestResource>> | This method returns a Promise that resolves to a ClerkPaginatedResponse of OrganizationMembershipRequest objects. |
Example
The following example demonstrates how to use the getMembershipRequests()
method to render a table of membership requests for the active organization. To ease the development process, the response or error message of a method will be displayed on the user interface.
For the following example, your HTML file should look like this:
index.html<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Clerk + JavaScript App</title> <style> /* Style for the table */ table { border-collapse: collapse; /* Collapse borders into a single border */ border: 1px solid black; /* Border for the entire table */ } /* Style for table cells */ td, th { border: 1px solid black; /* Border for each cell */ padding: 2px; /* Optional: Add padding to cells */ } </style> </head> <body> <div id="app"></div> <p id="error-container" hidden> Error: <span id="error-message"></span> </p> <h2>Membership Requests</h2> <table id="requests_table"> <thead> <tr> <th>User ID</th> <th>Identifier</th> <th>Status</th> <th id="add-member-head" hidden>Add member</th> </tr> </thead> <tbody id="requests_table_body"></tbody> </table> <p>Response:</p> <pre id="response"></pre> <script type="module" src="/main.js"></script> </body> </html>
And your JavaScript file should look like this:
main.jsimport Clerk from '@clerk/clerk-js'; // Initialize Clerk with your Clerk publishable key const clerk = new Clerk('{{pub_key}}'); await clerk.load(); if (clerk.user) { // Check for an active organization if (clerk.organization) { // Render list of organization membership requests async function renderMembershipRequests(organization, isAdmin) { try { const { data } = await organization.getMembershipRequests(); const membershipRequests = data; console.log(`getMembershipRequests:`, membershipRequests); membershipRequests.map((membershipRequest) => { const requestsTable = document.getElementById("requests_table"); const row = requestsTable.insertRow(); row.insertCell().textContent = membershipRequest.publicUserData.userId; row.insertCell().textContent = membershipRequest.publicUserData.identifier; row.insertCell().textContent = membershipRequest.status; // Add administrative actions: // Add member (removes request) if (isAdmin) { // Show add member button document.getElementById("add-member-head").removeAttribute("hidden"); // Get the user ID of the member const userId = membershipRequest.publicUserData.userId; // Add member to organization const addBtn = document.createElement("button"); addBtn.textContent = "Add member"; addBtn.addEventListener("click", async function (e) { e.preventDefault(); const role = "org:member"; await organization.addMember({ userId, role }) .then((res) => { document.getElementById("response").innerHTML = JSON.stringify(res); }) .catch((error) => { document.getElementById("error-container").removeAttribute("hidden"); document.getElementById("error-message").innerHTML = error.errors[0].longMessage; console.log("An error occurred:", error.errors); }); }); row.insertCell().appendChild(addBtn); } }); } catch (error) { document.getElementById("error-container").removeAttribute("hidden"); document.getElementById("error-message").innerHTML = error.errors[0].longMessage; console.log("An error occurred:", error.errors); } } /** * Checks if a user is an admin of the * currently active organization and * renders the organization's membership requests. */ async function checkAdminAndRenderRequests() { const organizationId = clerk.organization.id; const organizationMemberships = await clerk.user.getOrganizationMemberships(); const currentMembership = organizationMemberships.find( (membership) => membership.organization.id === organizationId ); const currentOrganization = currentMembership.organization; if (!currentOrganization) { return; } const isAdmin = currentMembership.role === "org:admin"; console.log(`Organization:`, currentOrganization); renderMembershipRequests(currentOrganization, isAdmin); } checkAdminAndRenderRequests(); } else { // If there is no active organization, // mount Clerk's <OrganizationSwitcher /> // to allow the user to set an organization as active document.getElementById("app").innerHTML = ` <h2>Select an organization to set it as active</h2> <div id="org-switcher"></div> `; const orgSwitcherDiv = document.getElementById("org-switcher"); clerk.mountOrganizationSwitcher(orgSwitcherDiv); } } else { document.getElementById("app").innerHTML = ` <div id="sign-in"></div> `; const signInDiv = document.getElementById("sign-in"); clerk.mountSignIn(signInDiv); }
index.html<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Clerk + JavaScript App</title> <style> /* Style for the table */ table { border-collapse: collapse; /* Collapse borders into a single border */ border: 1px solid black; /* Border for the entire table */ } /* Style for table cells */ td, th { border: 1px solid black; /* Border for each cell */ padding: 2px; /* Optional: Add padding to cells */ } </style> </head> <body> <div id="app"></div> <p id="error-container" hidden> Error: <span id="error-message"></span> </p> <h2>Membership Requests</h2> <table id="requests_table"> <thead> <tr> <th>User ID</th> <th>Identifier</th> <th>Status</th> <th id="add-member-head" hidden>Add member</th> </tr> </thead> <tbody id="requests_table_body"></tbody> </table> <p>Response:</p> <pre id="response"></pre> <!-- Initialize Clerk with your Clerk Publishable key and Frontend API URL --> <script async crossorigin="anonymous" data-clerk-publishable-key="{{pub_key}}" src="https://{{fapi_url}}/npm/@clerk/clerk-js@latest/dist/clerk.browser.js" type="text/javascript" ></script> <script> window.addEventListener("load", async function () { await Clerk.load(); if (Clerk.user) { // Check for an active organization if (Clerk.organization) { // Render list of organization membership requests async function renderMembershipRequests(organization, isAdmin) { try { const { data } = await organization.getMembershipRequests(); const membershipRequests = data; console.log(`getMembershipRequests:`, membershipRequests); membershipRequests.map((membershipRequest) => { const requestsTable = document.getElementById("requests_table"); const row = requestsTable.insertRow(); row.insertCell().textContent = membershipRequest.publicUserData.userId; row.insertCell().textContent = membershipRequest.publicUserData.identifier; row.insertCell().textContent = membershipRequest.status; // Add administrative actions: // Add member (removes request) if (isAdmin) { // Show add member button document.getElementById("add-member-head").removeAttribute("hidden"); // Get the user ID of the member const userId = membershipRequest.publicUserData.userId; // Add member to organization const addBtn = document.createElement("button"); addBtn.textContent = "Add member"; addBtn.addEventListener("click", async function (e) { e.preventDefault(); const role = "org:member"; await organization.addMember({ userId, role }) .then((res) => { document.getElementById("response").innerHTML = JSON.stringify(res); }) .catch((error) => { document.getElementById("error-container").removeAttribute("hidden"); document.getElementById("error-message").innerHTML = error.errors[0].longMessage; console.log("An error occurred:", error.errors); }); }); row.insertCell().appendChild(addBtn); } }); } catch (error) { document.getElementById("error-container").removeAttribute("hidden"); document.getElementById("error-message").innerHTML = error.errors[0].longMessage; console.log("An error occurred:", error.errors); } } /** * Checks if a user is an admin of the * currently active organization and * renders the organization's membership requests. */ async function checkAdminAndRenderRequests() { const organizationId = Clerk.organization.id; const organizationMemberships = await Clerk.user.getOrganizationMemberships(); const currentMembership = organizationMemberships.find( (membership) => membership.organization.id === organizationId ); const currentOrganization = currentMembership.organization; if (!currentOrganization) { return; } const isAdmin = currentMembership.role === "org:admin"; console.log(`Organization:`, currentOrganization); renderMembershipRequests(currentOrganization, isAdmin); } checkAdminAndRenderRequests(); } else { // If there is no active organization, // mount Clerk's <OrganizationSwitcher /> // to allow the user to set an organization as active document.getElementById("app").innerHTML = ` <h2>Select an organization to set it as active</h2> <div id="org-switcher"></div> `; const orgSwitcherDiv = document.getElementById("org-switcher"); Clerk.mountOrganizationSwitcher(orgSwitcherDiv); } } else { document.getElementById("app").innerHTML = ` <div id="sign-in"></div> `; const signInDiv = document.getElementById("sign-in"); Clerk.mountSignIn(signInDiv); } }); </script> </body> </html>
Last updated on March 26, 2024