Hi all,
I’m building a Retool mobile app with a barcode scanner to make looking up products faster. I have a scanner1
component set up, and I want it to work like this:
After scanning a barcode, the app should navigate to itemDetailScreen
and show the product whose id
matches the scanned value.
The barcode values correspond to the id
field in my productos
table.
What I’ve tried so far:
- I can get the scanned value using
scanner1.data
.
- I thought of using a JS query or transformer to filter the product list and find the matching item.
- But I’m not sure how to pass that selected item to
itemDetailScreen
, or how to set itemCollection.selectedItem
correctly before navigating.
Has anyone done something similar? What’s the best way to:
- Match the scanned barcode to an item by
id
,
- Set that item as the selected one,
- Navigate to
itemDetailScreen
with the right data?
Thanks a lot for any advice or examples!
Inventario Farmasi.json (71.6 KB)
1 Like
Hello @max.lopezzz,
Please update the event handler for scanner1
by changing the Navigation event type from Open to Capture, as shown in the attached screenshot.
Also, please update the transformer code in the filterItems
query with 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
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
};
});
// Filtering function
function filterItems(searchString, categoria, subcategoria, id) {
let filteredData = [...data];
// 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()
);
}
// Filter by exact id
if (id !== null && id !== undefined && id !== "") {
filteredData = filteredData.filter(item =>
item.id !== null &&
item.id !== undefined &&
item.id.toString() === id.toString()
);
}
return filteredData;
}
// Execute filtering and return result
return filterItems(
{{ busqueda.value || "" }},
{{ select1.value ?? null }},
{{ select2.value ?? null }},
{{ scanValue.value ?? null }}
);