Skip to content

Create Record List

createRecord_List_1 is a utility function in internal.js that dynamically generates list items with a consistent layout. It supports images, text fields, click handlers, and search functionality.

createRecord_List_1(
input, // Array of item data
id, // Unique ID prefix for generated elements
loader, // Section ID for loader (to hide when done)
viewer, // Container ID where list will be rendered
empty, // Section ID to show when list is empty
search // Section ID for search box (to show/hide)
);

Each item in the input array must be an array with 6 elements (indices 0-5):

[
// [0] - Click handler & search tags
{
search_tags: ["all", "keyword1", "keyword2"],
on_click: '{"operation": "link", "page_name": "page.html", ...}',
},
// [1] - Image/Icon
{ visible: true, url: "path/to/image.png" },
// [2] - Left Top Text (Title)
{
visible: true,
font_size: 14,
font_weight: 700,
colour: ["", ""],
opacity: 100,
value: "Product Name",
},
// [3] - Left Bottom Text (Subtitle)
{
visible: true,
font_size: 13,
font_weight: 400,
colour: ["", ""],
opacity: 80,
value: "7 packs (21,000 pcs)",
},
// [4] - Right Top Text
{
visible: true,
font_size: 14,
font_weight: 700,
colour: ["", ""],
opacity: 100,
value: "₹22,452",
},
// [5] - Right Bottom Text
{
visible: true,
font_size: 13,
font_weight: 400,
colour: ["", ""],
opacity: 90,
value: "Seeds",
},
];
{
search_tags: ["all", "searchable", "keywords"], // Used for filtering/search
on_click: '{"operation": "link", "page_name": "page.html", "parameters": {...}, "history": true}'
// or
on_click: '{"operation": "function", "function_name": "myFunction()"}'
// or
on_click: "" // No click handler
}
// Regular image
{ visible: true, url: "images/product.png" }
// Hide image
{ visible: false, url: "" }
// Special icons
{ visible: true, url: "icon" } // Shows info circle icon
{ visible: true, url: "info" } // Same as "icon"
{ visible: true, url: "user" } // Shows user placeholder image

Note: When using a regular image URL, the function automatically handles lazy loading with dattaio_queue_public_images().

All text fields share the same structure:

{
visible: true, // true = show, false = hide
font_size: 14, // Font size (e.g., 13, 14, 20, 26)
font_weight: 400, // 400 = normal, 700 = bold
colour: ["", ""], // ["red", "dark"] or ["green", "light"] or ["gray", "dark"]
opacity: 100, // 0-100 (80, 90, 100 are common)
value: "Display Text" // The actual text to display
}

Colour Format:

  • ["", ""] - Default color
  • ["red", "dark"] - Red text
  • ["green", "dark"] - Green text
  • ["gray", "dark"] - Gray text
  • ["grass", "dark"] - Theme green
var sender = [];
response.forEach((item) => {
sender.push([
{
search_tags: ["all", item.name],
on_click:
'{"operation": "link", "page_name": "detail.html", "parameters": {"id": "' +
item.id +
'"}}',
},
{ visible: true, url: item.image },
{
visible: true,
font_size: 14,
font_weight: 700,
colour: ["", ""],
opacity: 100,
value: item.name,
},
{
visible: true,
font_size: 13,
font_weight: 400,
colour: ["", ""],
opacity: 80,
value: item.quantity + " pcs",
},
{
visible: true,
font_size: 14,
font_weight: 700,
colour: ["", ""],
opacity: 100,
value: "" + formatNumber(item.price),
},
{
visible: true,
font_size: 13,
font_weight: 400,
colour: ["", ""],
opacity: 90,
value: item.category,
},
]);
});
createRecord_List_1(
sender,
"myList",
"section_loader",
"list_container",
"section_empty",
"section_search"
);
{ visible: false, url: "" }, // [1] Hide image
{ visible: true, value: "Title" }, // [2] Left top
{ visible: true, value: "Subtitle" }, // [3] Left bottom
{ visible: true, value: "₹100" }, // [4] Right top
{ visible: true, value: "Category" } // [5] Right bottom

Pattern 3: Simple 2-Column (Title + Price Only)

Section titled “Pattern 3: Simple 2-Column (Title + Price Only)”
{ visible: false, url: "" }, // [1] No image
{ visible: true, value: "Product Name" }, // [2] Left top
{ visible: false, value: "" }, // [3] Hide left bottom
{ visible: true, value: "₹100" }, // [4] Right top
{ visible: false, value: "" } // [5] Hide right bottom
{ visible: true, url: "icon" }, // [1] Shows info circle icon
// or
{ visible: true, url: "user" }, // [1] Shows user placeholder
// Green for profit/success
{
visible: true,
font_size: 13,
font_weight: 400,
colour: ["green", "dark"],
opacity: 90,
value: "₹500 Profit"
}
// Red for loss/error
{
visible: true,
font_size: 13,
font_weight: 400,
colour: ["red", "dark"],
opacity: 90,
value: "₹200 Loss"
}
// Gray for inactive
{
visible: true,
font_size: 13,
font_weight: 400,
colour: ["gray", "dark"],
opacity: 90,
value: "Inactive"
}

Pattern 6: Bold Gray Text (for emphasis without color)

Section titled “Pattern 6: Bold Gray Text (for emphasis without color)”
{
visible: true,
font_size: 14,
font_weight: 700, // Bold
colour: ["gray", "dark"],
opacity: 100,
value: "1.00 Pcs (Pcs)"
}
function available_stock_list_success(response) {
available_stock_response = response;
var sender = [];
var useEnglish = session("language_id").getValue() == 1;
response.forEach((item) => {
// Get product name based on language
var product_name = item.product_name;
if (!useEnglish && item.local_product_name != null) {
product_name = item.local_product_name;
}
// Build quantity text
let quantity_text = "";
if (item.product_group === "Cuttings") {
quantity_text =
convertToType(item.outer_quantity, "float") +
" " +
item.outer_unit_symbol;
} else {
quantity_text =
convertToType(item.outer_quantity, "float") +
" " +
item.outer_unit_symbol +
" (" +
convertToType(item.inner_quantity_1, "float") +
" " +
item.inner_unit_symbol_1 +
" )";
}
// Build amount text
var amount_text = "" + formatNumber(parseFloat(item.total_amount) || 0);
var product_group_text = item.product_group || "";
var image_url = item.product_image || "";
sender.push([
{
search_tags: ["all", item.product_name, item.product_group],
on_click:
'{"operation" : "link", "page_name" : "inventory-available-stock-individual", "parameters" : {"product_id" : "' +
item.product_id +
'"}, "history" : true}',
},
{ visible: true, url: image_url },
{
visible: true,
font_size: 14,
font_weight: 700,
colour: ["", ""],
opacity: 100,
value: product_name,
},
{
visible: true,
font_size: 13,
font_weight: 400,
colour: ["", ""],
opacity: 80,
value: quantity_text,
},
{
visible: true,
font_size: 14,
font_weight: 700,
colour: ["", ""],
opacity: 100,
value: amount_text,
},
{
visible: true,
font_size: 13,
font_weight: 400,
colour: ["", ""],
opacity: 90,
value: product_group_text,
},
]);
});
createRecord_List_1(
sender,
"availableStock",
"section_loader_stock",
"list_availableStock",
"section_empty",
"section_search_box"
);
}

Example: Minimal List (No Image, No Product Name)

Section titled “Example: Minimal List (No Image, No Product Name)”
function available_stock_individual_list_success(response) {
var sender = [];
var useEnglish = session("language_id").getValue() == 1;
response.forEach((item) => {
// Build quantity text
let quantity_text = "";
if (item.product_group === "Cuttings") {
quantity_text =
convertToType(item.outer_quantity, "float") +
" " +
item.outer_unit_symbol;
} else {
quantity_text =
convertToType(item.outer_quantity, "float") +
" " +
item.outer_unit_symbol +
" (" +
convertToType(item.inner_quantity_1, "float") +
" " +
item.inner_unit_symbol_1 +
" )";
}
var amount_text = "" + formatNumber(parseFloat(item.total_amount) || 0);
sender.push([
{
search_tags: ["all", item.product_name],
on_click: "",
},
{ visible: false, url: "" }, // No image
{
visible: true,
font_size: 14,
font_weight: 700,
colour: ["gray", "dark"], // Bold gray
opacity: 100,
value: quantity_text,
},
{
visible: false, // Hide left bottom
font_size: 13,
font_weight: 400,
colour: ["", ""],
opacity: 80,
value: "",
},
{
visible: true,
font_size: 14,
font_weight: 700,
colour: ["", ""],
opacity: 100,
value: amount_text,
},
{
visible: false, // Hide right bottom
font_size: 13,
font_weight: 400,
colour: ["", ""],
opacity: 90,
value: "",
},
]);
});
createRecord_List_1(
sender,
"availableStock",
"section_loader_stock",
"list_availableStock",
"section_empty",
"section_search_box"
);
}

The function expects the following HTML structure:

<div class="card card-style mb-0 mt-0" id="section_container">
<!-- Loader -->
<div class="content mb-0" id="section_loader" style="display: none">
<div class="loader-container pt-4">
<div class="loader loader-grey">
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
<!-- Empty State -->
<div class="content mb-0 mt-5" id="section_empty" style="display: none">
<h1>This list is empty</h1>
</div>
<!-- List Container -->
<div
class="content mb-0 mt-1 search-results-2"
id="list_container"
style="display: block; margin-left: 10px !important; margin-right: 5px !important"
>
<!-- List items will be inserted here -->
</div>
</div>
<!-- Search Box -->
<div id="section_search_box" class="search-box">
<input type="text" data-search-2 />
</div>
  1. Automatic Section Management

    • Hides loader when list is populated
    • Shows empty state when no items
    • Controls search box visibility
  2. Image Lazy Loading

    • Automatically queues images with dattaio_queue_public_images()
    • Shows loading placeholder while images load
  3. Click Handlers

    • Automatically attaches click handlers using Clickable.addNew()
    • Supports navigation, functions, and custom operations
  4. Search Integration

    • Items are searchable via data-filter-name attribute
    • Uses data-search-2 for filtering
  5. Responsive Design

    • Follows the app’s design system
    • Supports dividers between items
  • The function automatically adds dividers between items (except the first one)
  • Empty value strings will still render if visible: true
  • Use visible: false to completely hide elements
  • Image URLs should be relative paths (e.g., "images/product.png")
  • The function calls reset_search() after rendering
  • createRecord_List_1_Icon - Version with icon-only click handlers
  • createRecord_Box_Select_1 - For selectable box items
  • createRecord_List_Call - For callable list items

Copy this structure into your HTML page when using createRecord_List_1.

<!-- SEARCH BOX SECTION -->
<div class="content mt-1 p-1">
<div
id="section_search_box"
class="search-box bg-theme rounded-m shadow-l border-0"
style="display: block"
>
<i class="fa fa-search"></i>
<input
type="text"
inputmode="search"
id="input_search"
class="border-0 ankur_language"
placeholder="Search by keyword"
data-search-2
/>
<a href="#" class="clear-search-2 disabled mt-0"
><i class="fa fa-times color-red-light"></i
></a>
</div>
</div>
<!-- MAIN LIST CARD -->
<div class="card card-style mb-0 mt-0" id="section_container">
<!-- LOADER SECTION -->
<div
class="content mb-0"
id="section_loader"
style="height: 70px; display: none"
>
<div class="loader-container pt-4">
<div class="loader loader-grey">
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
<!-- EMPTY STATE SECTION -->
<div
class="content mb-0 mt-5"
id="section_empty"
style="height: 180px; text-align: center; display: none"
>
<h1 class="opacity-40 font-22 font-500 ankur_language" id="text_list_empty">
This list is empty
</h1>
<a
href="#"
id="button_reload"
class="ankur_language ankur_btn_1 btn close-menu btn-m rounded-sm shadow-l bg-dark-dark btn-center-m text-uppercase font-700 mt-5 opacity-30 app-nursery-click"
>Reload</a
>
</div>
<!-- LIST CONTAINER (Items will be inserted here dynamically) -->
<div
class="content mb-0 mt-1 search-results-2"
id="list_container"
style="display: block; margin-left: 10px !important; margin-right: 5px !important"
>
<!-- List items will be populated by createRecord_List_1 -->
</div>
</div>
<!-- NO RESULTS SECTION (Optional - for search) -->
<div class="card card-style pb-0 mt-1" id="section_noResults">
<div class="search-no-results-2 disabled mt-1 px-2">
<div class="content">
<h1 id="text_no_results" class="ankur_language">No Results</h1>
<p id="text_noResults_tag" class="ankur_language">
Your search brought up no results. Try using a different keyword.
</p>
</div>
</div>
</div>
createRecord_List_1(
sender, // Array of items
"uniqueId", // ID prefix (e.g., "myList")
"section_loader", // Loader section ID
"list_container", // List container ID
"section_empty", // Empty state section ID
"section_search_box" // Search box section ID
);
<!-- MAIN LIST CARD -->
<div class="card card-style mb-0 mt-0" id="section_container">
<!-- LOADER SECTION -->
<div
class="content mb-0"
id="section_loader"
style="height: 70px; display: none"
>
<div class="loader-container pt-4">
<div class="loader loader-grey">
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
<!-- EMPTY STATE SECTION -->
<div
class="content mb-0 mt-5"
id="section_empty"
style="height: 180px; text-align: center; display: none"
>
<h1 class="opacity-40 font-22 font-500 ankur_language" id="text_list_empty">
This list is empty
</h1>
</div>
<!-- LIST CONTAINER -->
<div
class="content mb-0 mt-1 search-results-2"
id="list_container"
style="display: block; margin-left: 10px !important; margin-right: 5px !important"
>
<!-- List items will be populated by createRecord_List_1 -->
</div>
</div>

Usage: Pass “none” for search parameter if no search box:

createRecord_List_1(
sender,
"myList",
"section_loader",
"list_container",
"section_empty",
"none"
);
<div class="page-content header-clear-medium">
<!-- SEARCH BOX -->
<div class="content mt-1 p-1">
<div
id="section_search_box"
class="search-box bg-theme rounded-m shadow-l border-0"
style="display: block"
>
<i class="fa fa-search"></i>
<input
type="text"
inputmode="search"
id="input_search"
class="border-0 ankur_language"
placeholder="Search by keyword"
data-search-2
/>
<a href="#" class="clear-search-2 disabled mt-0"
><i class="fa fa-times color-red-light"></i
></a>
</div>
</div>
<!-- MAIN LIST CARD -->
<div class="card card-style mb-0 mt-0" id="section_container">
<!-- LOADER -->
<div
class="content mb-0"
id="section_loader"
style="height: 70px; display: none"
>
<div class="loader-container pt-4">
<div class="loader loader-grey">
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
<!-- EMPTY STATE -->
<div
class="content mb-0 mt-5"
id="section_empty"
style="height: 180px; text-align: center; display: none"
>
<h1
class="opacity-40 font-22 font-500 ankur_language"
id="text_list_empty"
>
This list is empty
</h1>
<a
href="#"
id="button_reload"
class="ankur_language ankur_btn_1 btn close-menu btn-m rounded-sm shadow-l bg-dark-dark btn-center-m text-uppercase font-700 mt-5 opacity-30 app-nursery-click"
>Reload</a
>
</div>
<!-- LIST CONTAINER -->
<div
class="content mb-0 mt-1 search-results-2"
id="list_container"
style="display: block; margin-left: 10px !important; margin-right: 5px !important"
>
<!-- List items will be populated by createRecord_List_1 -->
</div>
</div>
<!-- NO RESULTS (Optional) -->
<div class="card card-style pb-0 mt-1" id="section_noResults">
<div class="search-no-results-2 disabled mt-1 px-2">
<div class="content">
<h1 id="text_no_results" class="ankur_language">No Results</h1>
<p id="text_noResults_tag" class="ankur_language">
Your search brought up no results. Try using a different keyword.
</p>
</div>
</div>
</div>
</div>
<div class="page-content header-clear-medium">
<!-- SEARCH BOX -->
<div class="content mt-1 p-1">
<div
id="section_search_box"
class="search-box bg-theme rounded-m shadow-l border-0"
style="display: block"
>
<i class="fa fa-search"></i>
<input
type="text"
inputmode="search"
id="input_search"
class="border-0 ankur_language"
placeholder="Search by keyword"
data-search-2
/>
<a href="#" class="clear-search-2 disabled mt-0"
><i class="fa fa-times color-red-light"></i
></a>
</div>
</div>
<!-- FILTER APPLIED SECTION -->
<div id="section_set_filter" class="content mt-n4" style="display: none">
<div class="card card-style mb-3 mt-1 ms-1 me-1" style="height: 50px">
<div class="content" style="height: 20px">
<div class="d-flex mt-n2">
<div class="align-self-center">
<h1 id="text_filter_applied" class="mb-0 font-14 ankur_language">
Filter Applied
</h1>
</div>
<div class="align-self-center ms-auto">
<h1
id="text_filter_value"
class="mb-0 font-14 font-600 opacity-80 ankur_language"
>
loading
</h1>
</div>
</div>
</div>
</div>
<div class="row pt-1 mb-3 p-0">
<div class="col-12">
<a
href="#"
id="button_reset_filter"
data-click='{"operation" : "function", "function_name" : "reset_filter"}'
class="ankur_language ankur_btn_1 btn btn-full btn-m font-700 text-uppercase rounded-sm shadow-l bg-grass-dark ms-2 me-2 app-nursery-click"
>Reset Filter</a
>
</div>
</div>
</div>
<!-- MAIN LIST CARD -->
<div class="card card-style mb-0 mt-0" id="section_container">
<!-- LOADER -->
<div
class="content mb-0"
id="section_loader"
style="height: 70px; display: none"
>
<div class="loader-container pt-4">
<div class="loader loader-grey">
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
<!-- EMPTY STATE -->
<div
class="content mb-0 mt-5"
id="section_empty"
style="height: 180px; text-align: center; display: none"
>
<h1
class="opacity-40 font-22 font-500 ankur_language"
id="text_list_empty"
>
This list is empty
</h1>
<a
href="#"
id="button_reload"
class="ankur_language ankur_btn_1 btn close-menu btn-m rounded-sm shadow-l bg-dark-dark btn-center-m text-uppercase font-700 mt-5 opacity-30 app-nursery-click"
>Reload</a
>
</div>
<!-- LIST CONTAINER -->
<div
class="content mb-0 mt-1 search-results-2"
id="list_container"
style="display: block; margin-left: 10px !important; margin-right: 5px !important"
>
<!-- List items will be populated by createRecord_List_1 -->
</div>
</div>
<!-- NO RESULTS (Optional) -->
<div class="card card-style pb-0 mt-1" id="section_noResults">
<div class="search-no-results-2 disabled mt-1 px-2">
<div class="content">
<h1 id="text_no_results" class="ankur_language">No Results</h1>
<p id="text_noResults_tag" class="ankur_language">
Your search brought up no results. Try using a different keyword.
</p>
</div>
</div>
</div>
</div>

Filter Menu Add this in your page, typically at the bottom:

Section titled “Filter Menu Add this in your page, typically at the bottom:”
<div id="menu_status_filter" class="menu menu-box-bottom menu-box-detached">
<div class="menu-title mt-n1">
<h1 id="text_statusFilter_header" class="font-22 ankur_language">
Filters
</h1>
<p
id="text_statusFilter_subHeader"
class="color-theme opacity-50 ankur_language"
>
Filter by category
</p>
<a href="#" class="close-menu"><i class="fa fa-times"></i></a>
</div>
<div class="divider mt-0 mb-0"></div>
<div class="content mb-0" id="section_status">
<div class="form-check interest-check">
<input
id="radio_filter_option1"
class="form-check-input ankur_language"
name="filter"
type="radio"
value=""
data-click='{"operation" : "function", "function_name" : "my_filter_function", "parameters" : ["Option1"]}'
/>
<label
id="text_filter_option1"
class="form-check-label rounded-m font-12 ankur_language"
for="radio_filter_option1"
style="padding-left: 10px !important; padding-right: 10px !important"
>Option 1</label
>
</div>
<div class="form-check interest-check">
<input
id="radio_filter_option2"
class="form-check-input ankur_language"
name="filter"
type="radio"
value=""
data-click='{"operation" : "function", "function_name" : "my_filter_function", "parameters" : ["Option2"]}'
/>
<label
id="text_filter_option2"
class="form-check-label rounded-m font-12 ankur_language"
for="radio_filter_option2"
style="padding-left: 10px !important; padding-right: 10px !important"
>Option 2</label
>
</div>
<!-- Add more filter options as needed -->
</div>
</div>

Add to functions.js:

function my_filter_function(selected) {
// Handle array parameter from data-click
var filterValue = Array.isArray(selected) ? selected[0] : selected;
var sender = [];
my_response.forEach((item) => {
// Filter by your criteria
if (filterValue == "none" || item.category === filterValue) {
sender.push([
{ search_tags: ["all", item.name], on_click: "..." },
{ visible: true, url: item.image },
// ... rest of your item data
]);
}
});
createRecord_List_1(
sender,
"myList",
"section_loader",
"list_container",
"section_empty",
"section_search_box"
);
text("text_filter_value").setValue(filterValue);
section("section_set_filter").show();
section("section_search_box").hide();
}
function reset_filter() {
my_filter_function("none");
Radio.deselectAll("filter");
section("section_set_filter").hide();
section("section_search_box").show();
}
  • section_loader - Loader section
  • section_empty - Empty state section
  • list_container - Where items are rendered
  • section_search_box - Search box (optional, use “none” if not present)
  • section_set_filter - Filter applied section
  • text_filter_applied - Filter label text
  • text_filter_value - Current filter value
  • button_reset_filter - Reset filter button
  • menu_status_filter - Filter menu
  • section_status - Filter options container
  • section_noResults - No search results section
  • text_list_empty - Empty list message
  • button_reload - Reload button
  • search-results-2 - Required for search filtering
  • data-search-2 - Required on search input
  • clear-search-2 - Required for clear search button
  • loader loader-grey - Loader animation
  • search-no-results-2 - No results styling