This app was built on several areas of the Wix Blocks editor. Here is how we did it.
The Widgets and Design area is where you create the user interface of your widgets, using drag and drop Wix elements. In this area we:
initRepeater()
function, which sets the number of items according to the user's choice and opens the Recipe Lightbox with the relevant data.import { openLightbox } from 'wix-window-frontend'; //read more: https://www.wix.com/velo/reference/wix-window-frontend/lightbox let itemsCount; $w.onReady(async function () { await initRepeater(); }); $widget.onPropsChanged(async (oldProps, newProps) => { await initRepeater(); }); //Initialize the repeater data and sets the page size to display a specific number or all items based on user choice. async function initRepeater() { switch ($widget.props.recipesVisibility) { case 'specificNumber': itemsCount = $widget.props.itemsToDisplay; break; case 'allItems': $w("#recipeDataset").onReady(() => itemsCount = $w("#recipeDataset").getTotalCount()); break; } $w("#recipeDataset").setPageSize(itemsCount) .catch((err) => { let errMsg = err.message; let errCode = err.code; }); // Open a lightbox with detailed recipe information when the "Get the Recipe" button of each repeater item is clicked. $w('#recipesRepeater').onItemReady(($item, itemData) => { $item('#recipeLearnMore').onClick(async () => { await openLightbox('Recipe Lightbox', { recipeData: itemData }); }); }); }
import { lightbox } from 'wix-window-frontend'; import wixWindowFrontend from 'wix-window-frontend'; $w.onReady(function () { // Get the recipe data passed through the lightbox context const receivedData = lightbox.getContext().recipeData; // Set the lightbox elements with recipe data $w('#recipeTitle').text = receivedData.title; $w('#recipeAuthor').text = receivedData.authorName; $w('#recipeDuration').text = receivedData.duration.toString(); $w('#recipeDifficulty').text = receivedData.difficulty; $w('#recipeRating').value = receivedData.rating; $w('#recipeDescription').text = receivedData.description; $w('#recipeIngredients').html = receivedData.ingredients; $w('#recipeInstructions').html = receivedData.instructions; $w('#recipeImage').src = receivedData.image; //Close the lightbox when the close button is clicked $w('#XButton').onClick(() => { wixWindowFrontend.lightbox.close(); }) });
CMS database collections in Blocks let you store data in an app and on a site. In this area, we created a database collection that contains all the recipes. We:
Added a collection to hold the recipe data (name, image, etc).
Connected the repeater elements to the collection fields. This is a way to present dynamic data without code
Image
field to the recipe image.App Dashboard
The app dashboard is used as the backoffice of this app, to allow site builders to manage the recipes collection. In this area, we:
// Handle navigation between 'recipes' and 'form' states $w.onReady(async function () { $w('#addButton').onClick((e) => { $w('#multiStateBox1').changeState('form'); }) $w('#cancelBtn').onClick((e) => { $w('#multiStateBox1').changeState('recipes'); }) $w('#saveBtn').onClick((e) => { $w('#multiStateBox1').changeState('recipes'); }) });
Custom panels let site builders customize widget settings. In our case, the settings include the number of recipes to present. In this area, we:
import wixWidget from 'wix-widget'; import wixEditor from 'wix-editor'; import wixApplication from 'wix-application'; $w.onReady(async function () { //Fetch the current widget properties const props = await wixWidget.getProps(); //Loads the panel element with the current widget properties values $w('#recipesVisibilityRadioButton').value = props.recipesVisibility; ($w('#recipesVisibilityRadioButton').value == 'specificNumber') ? $w('#recipesSlider').expand(): $w('#recipesSlider').collapse(); $w('#recipesSlider').value = props.itemsToDisplay; //Handle value changes in the panel elements $w('#recipesSlider').onChange(async event => { await wixWidget.setProps({ itemsToDisplay: $w('#recipesSlider').value }); }); $w('#recipesVisibilityRadioButton').onChange(async event => { $w('#recipesVisibilityRadioButton').value == 'specificNumber' ? $w('#recipesSlider').expand() : $w('#recipesSlider').collapse(); await wixWidget.setProps({ recipesVisibility: $w('#recipesVisibilityRadioButton').value }); }); // Open dashboard page from the 'Manage Recipes' button const appInstance = await wixApplication.getDecodedAppInstance(); $w('#manageRecipesButton').onClick(() => { wixEditor.openDashboardPanel({ url: `app/${appInstance.appDefId}` }); }); });
In the Configuration area, we:
Changed the name of the widget’s main action button to Manage Recipes.
Connected this action button to the dashboard page.
Added another main action button, and named it Settings.
Connected this action button to the Recipes List Settings panel.
The app and widget installation settings let you configure various aspects of the installation process. In this area, we:
Defined the Recipe Feed widget to be automatically added to the current page on a site.
Defined the Recipe Lightbox widget to be added as a lightbox, and set its default presets for desktop and mobile.
Experience tip - preset visibility: By default, all design presets are shown in a site's Add + panel. To give users a better experience, we removed irrelevant presets from this panel and left them only in the presets panel.
Added preset images. Make sure to change these images to your own if you change the appearance of the app.