Node.js dynamic routing to brand page

My setup

  • wappler 6.8
  • macos
  • nodejs
  • mysql
  • docker

I'd like to create a portal that is dynamic. When a user goes to /b/:brand/ route I would like the page to load the logo and content based on the brand.

I believe I would have to create a database with a brand table like so:
2025-01-03_15-21-23

Then somehow query that database and have some conditionals.

I've successfully created the dynamic route and pointed to my brand.ejs page which is tied to the brand-layout.ejs. I think the next step is to create either a server connect or api action on the brand page inside the right App Structure panel?

I'm really new to wappler but not web development. Any guidance is appreciated.

Hey @TT, you're on the right path. A server connect is the best approach to query for the data based on the brand id.

This should help.

Thanks for the resource. I've seen it before and read it probably 10 times but the problem is the version is different and the screenshots don't make sense at times.

I have serverconnect2 which has my query.

Currently getting this error when loading the page which makes me think there's something wrong with how the query was setup:
{
"status": "500",
"message": "Undefined binding(s) detected for keys [0] when compiling RAW query: SELECT id, name, layout, theme FROM brands WHERE name = ?",
"stack": "Error: Undefined binding(s) detected for keys [0] when compiling RAW query: SELECT id, name, layout, theme FROM brands WHERE name = ?\n at Raw.toSQL (/opt/node_app/node_modules/knex/lib/raw.js:110:13)\n at ensureConnectionCallback (/opt/node_app/node_modules/knex/lib/execution/internal/ensure-connection-callback.js:4:30)\n at Runner.ensureConnection (/opt/node_app/node_modules/knex/lib/execution/runner.js:318:20)\n at process.processTicksAndRejections (node:internal/process/task_queues:105:5)\n at async Runner.run (/opt/node_app/node_modules/knex/lib/execution/runner.js:30:19)\n at async App.custom (/opt/node_app/lib/modules/dbupdater.js:367:23)\n at async App._exec (/opt/node_app/lib/core/app.js:717:22)\n at async App.exec (/opt/node_app/lib/core/app.js:653:5)\n at async App.define (/opt/node_app/lib/core/app.js:635:5)"
}

Query screenshots:

Can you show the server connect properties on your page?

Also, does the test return records in the custom query and you're only having an issue on the brand page?

Should :brand not be :P1

Named parameters work, at least in custom queries.

1 Like

Here's my server connect properties (i think):

I do find it kind of odd there's only 1 option for server side data at the app level:

I'm using getBrandData to set meta title on the layout.

Yes the test query works, the brand page doesn't I must not be understanding how binding works or something very basic.

brand page error

Have you defined the Query Parameters on the page?

image

Hi TT,

Instead of setting up brand as a $_PARAM variable, set it up as a $_GET variable. Then it will appear as a parameter under the INPUT PARAMETERS server connect properties in the UI.

To set a dynamic meta title on the layout, the binding of $_PARAM.brand is incorrect. Instead, bind the value of title to the brand value returned in the API.

My brand page is passing brand from the route to the layout. Are you saying this is incorrect?

The brand shows up just fine in the title. What I am trying to do now is expand a little and try and control content by using the database and the route parameter. Maybe that isn't the right architecture.

I successfully created the route using serverconnect1 but when I try and add serverconnect2, with validateBrand action I get the error above regarding status 500 Undefined bindings(s). So maybe I'm not setting up the custom database query or action correctly. Kind of frustrating not knowing where my knowledge gap is, unfortunately.

Hi TT,

As @Cheese mentioned in the previous post, you need to define query parameters on the layout page and then bind the query parameter to a $_GET variable in the Server Action. I have listed the steps for this workflow below.

  1. Define Query Parameters on the Layout page. Let's call it brand_id.
  2. Create a Server Action, let's name it brand_information.
  3. Add a $_GET variable in the above Server Action - filter_brand_id.
  4. Use the var filter_brand_id to filter information from the database table. A custom query is not necessary to get this information.
  5. Add a Server Connect on the layout page - sc_brand_information and select the Server Action as above.
  6. The above Server Connect will show filter_band_id as an Input Parameter - click on the dynamic binding icon (thunderbolt) and select the query parameter you created earlier. This will appear as query.brand_id in the code as below:
<dmx-serverconnect id="sc_brand_information" url="/api/brand_information" dmx-param:filter_brand_id="query.brand_id"></dmx-serverconnect>

When you navigate to the route /b/:brand_id (renamed from brand to brand_id to match the query parameter) where :brand_id is expecting a value to filter the data. E.g. if you navigate to the route /b/1234, it will send the brand_id value as 1234 to the Server Action and filter the data accordingly.

You can also then use the same Server Action / Server Connect for the Server Side Data binding to get the title etc.

1 Like

It's interesting that defining the query param and using $_GET in the server connect action seems to work to get brand specific content on the layout page.

Now when trying to set the page with the server connect nothing shows up.

Check that the App ID's match otherwise query parameters won't be recognised (cookies are also reliant upon this matching). This has irritated me for years but it is the way it is and maybe responsible...? The App ID needs to match your Layout page App ID across all Content Pages. You can set the App ID by clicking on the App icon at the top of the App Structure (the cube looking icon).

It never occurred to me that app id should be the same thanks for letting me know. Whenever I create a page or layout the app id is automatically created for me.

I did match the layout and page to main but its still not showing the query.name value.

Restart the application and try again. Sometimes it needs a little refresh and maybe clear cache too..

I'm still not sure why this is a feature of Wappler and not a bug as it causes problems for a lot of Users new to Wappler and even some of us 'veterans' alike especially for anything state/query related (the Data Store also has issues if the App ID is mismatched). Better the Devil you know is what I say. I am by no means knocking Wappler. There is quite obviously some reason for it but it escapes me at this moment (my memory is terrible but has been explained to me on more than one occasion).

:wink:

Restarting didn't work. I'll have to try this again tomorrow.

It's weird doing something simple as pulling from a db table and inserting it onto a page is this difficult but I suppose wappler has a steep learning curve.

Remember to see some query bug report, doesn't query manager work as a workaround? :thinking:

From the last screenshot you have posted, I notice a couple of places in the app structures that need to be modified.

  1. Change the App Root App property from Body to Page.
  2. It seems you are binding the value of title with local query value query.name. Instead, it should be bound to the name field value being returned from the SC brand/brand_information.

I will also recommend working with dynamic bindings in general initially. E.g. display a brand name value being returned from the filtered database query on a content page (example below). This will help you in gaining an understanding of how App Connect and Server Actions operate in a dynamic environment and how to troubleshoot if there are any issues.

<p>{{sc_brand_info.data.q_brand_info.brand_name}}</p>
1 Like