Title: Help: Barcode Scanner with Fallback to Manual Product Linking in Retool Mobile
Hi everyone
I'm building a mobile app and need help implementing a workflow for barcode scanning and fallback selection .
What I want to do:
Where I’m stuck:
I'm not sure how to:
Detect when the barcode doesn’t match anything in the database.
Show the popup select in that case.
Update the codigo_de_barras
field for the selected product with the scanned barcode.
Any advice on the best way to implement this logic with Retool mobile components and queries would be appreciated!
Thanks in advance
Inventario Farmasi.json (68.9 KB)
bowe
June 5, 2025, 7:00pm
3
Hey @max.lopezzz
Being as there is not a pop up / modal component in Retool Mobile, I would suggest using conditional logic to show and hide the components on the itemDetailScreen.
Flow:
Scan barcode
Send user to itemDetailScreen
Query DB or use your fitlerItems transformer using scanValue to get a result.
if filterItems returns an Empty array, I would use this as an indicator to show/hide relevant components on the itemDetailScreen.
For example if {{filterItems.value}} is empty it will be false, so you can use the hidden field on itemImage to hide it on the screen. Same for itemKeyValue.
on this screen, I would do the inverse for a form that the user can use to look up the item and assign it the barcode in the DB using another query triggered from submitting that form.
Hope this helps point you in the right direction!
I changed my filterItems logic to the following:
// Get raw columnar data from query
const rawData = {{ getItems.data }};
// Handle case where data might be null or empty
if (!rawData || !rawData.nombre || !Array.isArray(rawData.nombre)) {
return [];
}
// Convert columnar format to array of objects (include codigo_de_barras as int)
const data = rawData.nombre.map((_, index) => {
return {
id: rawData.id?.[index] ?? null,
nombre: rawData.nombre?.[index] ?? null,
cantidad: rawData.cantidad?.[index] ?? null,
costo: rawData.costo?.[index] ?? null,
precio: rawData.precio?.[index] ?? null,
categoria: rawData.categoria?.[index] ?? null,
subcategoria: rawData.subcategoria?.[index] ?? null,
descripcion: rawData.descripcion?.[index] ?? null,
foto: rawData.foto?.[index] ?? null,
codigo_de_barras: rawData.codigo_de_barras?.[index] !== undefined && rawData.codigo_de_barras?.[index] !== null
? parseInt(rawData.codigo_de_barras[index], 10)
: null
};
});
// Filtering function (without scanValue/id filtering)
function filterItems(searchString, categoria, subcategoria, barcode) {
let filteredData = [...data];
// Filter by barcode if scanner1 has a value
if (barcode !== null && barcode !== undefined && barcode !== "") {
const barcodeInt = parseInt(barcode.toString().trim(), 10);
if (!isNaN(barcodeInt)) {
filteredData = filteredData.filter(item =>
item.codigo_de_barras !== null &&
item.codigo_de_barras === barcodeInt
);
// Return early since barcode is an exact match
return filteredData;
}
}
// Filter by search string in 'nombre'
if (searchString) {
const lowerCaseSearch = searchString.toLowerCase();
filteredData = filteredData.filter(item =>
item.nombre && item.nombre.toLowerCase().includes(lowerCaseSearch)
);
}
// Filter by categoria
if (categoria !== null && categoria !== undefined && categoria !== "") {
filteredData = filteredData.filter(item =>
item.categoria !== null &&
item.categoria !== undefined &&
item.categoria.toString() === categoria.toString()
);
}
// Filter by subcategoria
if (subcategoria !== null && subcategoria !== undefined && subcategoria !== "") {
filteredData = filteredData.filter(item =>
item.subcategoria !== null &&
item.subcategoria !== undefined &&
item.subcategoria.toString() === subcategoria.toString()
);
}
return filteredData;
}
// Execute filtering and return result
return filterItems(
{{ busqueda.value || "" }},
{{ select1.value ?? null }},
{{ select2.value ?? null }},
{{ scanner1.value ?? null }}
);
Is this correct?
I don't really understand how to use the hidden fields, could you help me out please? Thank you so much in advance