DevExtreme v25.2 is now available.

Explore our newest features/capabilities and share your thoughts with us.

Your search did not match any results.

JavaScript/jQuery Tree List - AI Columns

DevExtreme JavaScript TreeList allows you to add multiple AI columns to the JavaScript TreeList. These columns auto generate meaningful cell values based on component data and a custom prompt, transforming DevExtreme JavaScript TreeList into an AI-powered data analysis tool. In this demo, an AI column is fixed to the right side of the component.

Backend API
$(() => { const deployment = 'gpt-4o-mini'; const apiVersion = '2024-02-01'; const endpoint = 'https://public-api.devexpress.com/demo-openai'; const apiKey = 'DEMO'; const aiService = new AzureOpenAI({ dangerouslyAllowBrowser: true, deployment, endpoint, apiVersion, apiKey, }); async function getAIResponse(messages, signal) { const params = { messages, model: deployment, max_tokens: 1000, temperature: 0.7, }; const response = await aiService.chat.completions .create(params, { signal }); const result = response.choices[0].message?.content; return result; } async function getAIResponseRecursive(messages, signal) { return getAIResponse(messages, signal) .catch(async (error) => { if (!error.message.includes('Connection error')) { return Promise.reject(error); } DevExpress.ui.notify({ message: 'Our demo AI service reached a temporary request limit. Retrying in 30 seconds.', width: 'auto', type: 'error', displayTime: 5000, }); await new Promise((resolve) => setTimeout(resolve, 30000)); return getAIResponseRecursive(messages, signal); }); } const aiIntegration = new DevExpress.aiIntegration({ sendRequest({ prompt }) { const isValidRequest = JSON.stringify(prompt.user).length < 5000; if (!isValidRequest) { return { promise: Promise.reject(new Error('Request is too long. Specify a shorter prompt.')), abort: () => {}, }; } const controller = new AbortController(); const signal = controller.signal; const aiPrompt = [ { role: 'system', content: prompt.system }, { role: 'user', content: prompt.user }, ]; const promise = getAIResponseRecursive(aiPrompt, signal); const result = { promise, abort: () => { controller.abort(); }, }; return result; }, }); const createNameTemplate = (employee) => { const { ID, First_Name, Last_Name, } = employee; if (!ID || !First_Name || !Last_Name) { return $('<div>').text(''); } const nameWrapper = $('<div>').addClass('name__wrapper'); const imgWrapper = $('<div>').addClass('name__img-wrapper'); const img = $('<img>').addClass('name__img'); img.attr({ src: `../../../../images/employees/new/${First_Name} ${Last_Name}.jpg`, alt: `${First_Name} ${Last_Name}`, }); imgWrapper.append(img); nameWrapper.append(imgWrapper); const textWrapper = $('<div>').addClass('name__text-wrapper'); const firstNameText = $('<div>').addClass('name__text').text(First_Name); const lastNameText = $('<div>').addClass('name__text').text(Last_Name); textWrapper.append(firstNameText, lastNameText); nameWrapper.append(textWrapper); return nameWrapper; }; const createStatusTemplate = (status) => $('<div>') .append( $('<div>').addClass('indicator'), ) .append( $('<div>').text(status), ) .addClass('status') .toggleClass('status--salaried', status === 'Salaried') .toggleClass('status--commission', status === 'Commission') .toggleClass('status--terminated', status === 'Terminated'); $('#treeList').dxTreeList({ dataSource: employees, showBorders: true, keyExpr: 'ID', parentIdExpr: 'Head_ID', autoExpandAll: true, aiIntegration, scrolling: { mode: 'standard', }, paging: { enabled: true, pageSize: 10, }, columns: [ { caption: 'Employee', width: 260, cellTemplate: (container, options) => { const employee = options.data; const imageWrapper = createNameTemplate(employee); container.append(imageWrapper); }, cssClass: 'name_cell', }, { dataField: 'Title', caption: 'Position', width: 140, }, { dataField: 'Status', cellTemplate: (container, options) => { const status = options.data.Status; const statusWrapper = createStatusTemplate(status); container.append(statusWrapper); }, minWidth: 180, }, { dataField: 'City', width: 180, }, { dataField: 'State', width: 140, }, { dataField: 'Email', minWidth: 200, }, { name: 'AI Column', caption: 'AI Column', type: 'ai', ai: { prompt: 'Identify the department where the employee works. Select from the following department list: "Management", "Human Resources", "IT", "Shipping", "Support", "Sales", "Engineering". Use "Engineering" if you cannot find a better match.', mode: 'auto', noDataText: 'No data', }, width: 180, fixed: true, fixedPosition: 'right', cssClass: 'ai__cell', }, ], onAIColumnRequestCreating(e) { e.data = e.data.map((item) => ({ ID: item.ID, First_Name: item.First_Name, Last_Name: item.Last_Name, Title: item.Title, })); }, }); });
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" lang="en"> <head> <title>DevExtreme Demo</title> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" /> <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/25.2.3/css/dx.light.css" /> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script>window.jQuery || document.write(decodeURIComponent('%3Cscript src="js/jquery.min.js"%3E%3C/script%3E'))</script> <script src="js/dx.all.js?v=25.2.3"></script> <script src="js/dx.ai-integration.js"></script> <script type="module"> import { AzureOpenAI } from "https://esm.sh/openai@4.73.1"; window.AzureOpenAI = AzureOpenAI; </script> <script src="data.js"></script> <script src="index.js"></script> <link rel="stylesheet" type="text/css" href="styles.css" /> </head> <body class="dx-viewport"> <div class="demo-container"> <div id="tree-list-demo"> <div id="treeList"></div> </div> </div> </body> </html>
#treeList { min-height: 560px; } #treeList .ai__cell { background-color: var(--dx-datagrid-row-alternation-bg); } #treeList .name_cell > div { align-items: flex-end; } .name__wrapper { display: flex; align-items: center; gap: 8px; } .name__img-wrapper { width: 40px; height: 40px; border: var(--dx-border-width) solid var(--dx-color-border); border-radius: 50%; cursor: pointer; } .name__img-wrapper img { width: 100%; height: 100%; object-fit: cover; object-position: center; border-radius: 50%; } .name__text-wrapper { width: calc(100% - 48px); } .name__text { margin: 0; padding: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .status { display: flex; align-items: center; } .status--salaried { color: var(--dx-color-success); } .status--commission { color: #f7630c; } .status--terminated { color: var(--dx-color-danger); } .indicator { background-color: currentcolor; margin-right: 8px; border-radius: 50%; height: 12px; width: 12px; }
const employees = [{ ID: 1, Head_ID: 0, First_Name: 'John', Last_Name: 'Heart', Prefix: 'Mr.', Title: 'CEO', City: 'Los Angeles', State: 'California', Email: 'jheart@dx-email.com', Skype: 'jheart_DX_skype', Mobile_Phone: '(213) 555-9392', Birth_Date: '1964-03-16', Hire_Date: '1995-01-15', Status: 'Salaried', }, { ID: 3, Head_ID: 1, First_Name: 'Arthur', Last_Name: 'Miller', Prefix: 'Mr.', Title: 'CTO', City: 'Los Angeles', State: 'California', Email: 'arthurm@dx-email.com', Mobile_Phone: '+1 (310) 555-8583', Birth_Date: '1972-07-11', Hire_Date: '2007-12-18', Status: 'Salaried', }, { ID: 4, Head_ID: 1, First_Name: 'Robert', Last_Name: 'Reagan', Prefix: 'Mr.', Title: 'CMO', City: 'Pasadena', State: 'California', Email: 'robertr@dx-email.com', Mobile_Phone: '+1 (818) 555-2387', Birth_Date: '1974-09-07', Hire_Date: '2002-11-08', Status: 'Salaried', }, { ID: 5, Head_ID: 1, First_Name: 'Greta', Last_Name: 'Sims', Prefix: 'Ms.', Title: 'HR Manager', City: 'Alhambra', State: 'California', Email: 'gretas@dx-email.com', Mobile_Phone: '+1 (818) 555-6546', Birth_Date: '1977-11-22', Hire_Date: '1998-04-23', Status: 'Salaried', }, { ID: 6, Head_ID: 3, First_Name: 'Brett', Last_Name: 'Wade', Prefix: 'Mr.', Title: 'IT Manager', City: 'San Marino', State: 'California', Email: 'brettw@dx-email.com', Mobile_Phone: '+1 (626) 555-0358', Birth_Date: '1968-12-01', Hire_Date: '2009-03-06', Status: 'Salaried', }, { ID: 7, Head_ID: 5, First_Name: 'Sandra', Last_Name: 'Johnson', Prefix: 'Mrs.', Title: 'Controller', City: 'Long Beach', State: 'California', Email: 'sandraj@dx-email.com', Mobile_Phone: '+1 (562) 555-2082', Birth_Date: '1974-11-15', Hire_Date: '2005-05-11', Status: 'Salaried', }, { ID: 21, Head_ID: 6, First_Name: 'Taylor', Last_Name: 'Riley', Prefix: 'Mr.', Title: 'Network Admin', City: 'West Hollywood', State: 'California', Email: 'taylorr@dx-email.com', Mobile_Phone: '+1 (310) 555-7276', Birth_Date: '1982-08-14', Hire_Date: '2012-04-14', Status: 'Salaried', }, { ID: 22, Head_ID: 6, First_Name: 'Amelia', Last_Name: 'Harper', Prefix: 'Mrs.', Title: 'Network Admin', City: 'Los Angeles', State: 'California', Email: 'ameliah@dx-email.com', Mobile_Phone: '+1 (213) 555-4276', Birth_Date: '1983-11-19', Hire_Date: '2011-02-10', Status: 'Salaried', }, { ID: 25, Head_ID: 6, First_Name: 'Karen', Last_Name: 'Goodson', Prefix: 'Miss', Title: 'Programmer', City: 'South Pasadena', State: 'California', Email: 'kareng@dx-email.com', Mobile_Phone: '+1 (626) 555-0908', Birth_Date: '1987-04-26', Hire_Date: '2011-03-14', Status: 'Salaried', }, { ID: 28, Head_ID: 6, First_Name: 'Morgan', Last_Name: 'Kennedy', Prefix: 'Mrs.', Title: 'Graphic Designer', City: 'San Fernando Valley', State: 'California', Email: 'morgank@dx-email.com', Mobile_Phone: '+1 (818) 555-8238', Birth_Date: '1984-07-17', Hire_Date: '2012-01-11', Status: 'Salaried', }, { ID: 29, Head_ID: 28, First_Name: 'Violet', Last_Name: 'Bailey', Prefix: 'Ms.', Title: 'Jr Graphic Designer', City: 'La Canada', State: 'California', Email: 'violetb@dx-email.com', Mobile_Phone: '+1 (818) 555-2478', Birth_Date: '1985-06-10', Hire_Date: '2012-01-19', Status: 'Salaried', }, { ID: 32, Head_ID: 3, First_Name: 'Bart', Last_Name: 'Arnaz', Prefix: 'Mr.', Title: 'Director of Engineering', City: 'Irvine', State: 'California', Email: 'barta@dx-email.com', Mobile_Phone: '+1 (714) 555-2000', Birth_Date: '1979-11-01', Hire_Date: '2008-06-29', Status: 'Salaried', }, { ID: 36, Head_ID: 32, First_Name: 'Samantha', Last_Name: 'Piper', Prefix: 'Ms.', Title: 'Engineer', City: 'Los Angeles', State: 'California', Email: 'samanthap@dx-email.com', Mobile_Phone: '+1 (323) 555-4512', Birth_Date: '1984-12-01', Hire_Date: '2008-01-22', Status: 'Salaried', }, { ID: 38, Head_ID: 32, First_Name: 'Terry', Last_Name: 'Bradley', Prefix: 'Mr.', Title: 'QA Engineer', City: 'Simi Valley', State: 'California', Email: 'terryb@dx-email.com', Mobile_Phone: '+1 (805) 555-2788', Birth_Date: '1984-01-09', Hire_Date: '2007-10-18', Status: 'Salaried', }, { ID: 44, Head_ID: 4, First_Name: 'Clark', Last_Name: 'Morgan', Prefix: 'Mr.', Title: 'Retail Sales Manager', City: 'Martinez', State: 'California', Email: 'clarkm@dx-email.com', Mobile_Phone: '+1 (925) 555-2525', Birth_Date: '1988-04-07', Hire_Date: '2012-04-11', Status: 'Commission', }, { ID: 45, Head_ID: 4, First_Name: 'Todd', Last_Name: 'Hoffman', Prefix: 'Mr.', Title: 'Retail Sales Manager', City: 'Livermore', State: 'California', Email: 'toddh@dx-email.com', Mobile_Phone: '+1 (925) 555-3579', Birth_Date: '1987-03-25', Hire_Date: '2012-04-19', Status: 'Commission', }, { ID: 48, Head_ID: 32, First_Name: 'Brad', Last_Name: 'Farkus', Prefix: 'Mr.', Title: 'Engineer', City: 'Los Angeles', State: 'California', Email: 'bradf@dx-email.com', Mobile_Phone: '+1 (213) 555-3626', Birth_Date: '1991-03-17', Hire_Date: '2010-04-15', Status: 'Terminated', }, { ID: 51, Head_ID: 32, First_Name: 'Stu', Last_Name: 'Pizaro', Prefix: 'Mr.', Title: 'Engineer', City: 'Los Angeles', State: 'California', Email: 'stu@dx-email.com', Mobile_Phone: '+1 (213) 555-2552', Birth_Date: '1985-09-11', Hire_Date: '2011-07-19', Status: 'Terminated', }];

AI services used for this demo have been rate and data limited. As such, you may experience performance-related delays when exploring the capabilities of JavaScript TreeList AI Columns.

When connected to your own AI model/service without rate and data limits, JavaScript TreeList AI Columns will perform seamlessly, without artificial delays. Note that DevExtreme does not offer an AI REST API and does not ship any built-in LLMs/SLMs.

This demo instructs the AI service to identify the department name associated with each employee. You can modify the default prompt or enter a custom prompt in the AI column header menu.

To integrate an AI column into the DevExtreme JavaScript TreeList, you must:

  • Configure the aiIntegration property at the component or column level (aiIntegration or columns[].ai.aiIntegration).
  • Set the column type to "ai".
  • Specify the column name.
  • Configure columns[].ai options, such as generation mode, predefined prompt, and no data text (displayed when the AI service returns no data for a row).

Our DevExtreme JavaScript TreeList component uses all visible row data in AI requests, including fields not bound to a column and hidden column fields. This data gives LLMs broader context, but increases the use of AI resources. To limit data included in AI requests, modify the AIColumnRequestCreatingEvent.data parameter in the onAIColumnRequestCreating event handler.