🚀 Welcome to MDriven Learn –  MDriven is now on Discord!  Don’t miss the latest Release Notes.
HTML Frontend Tips and Tricks
This page was created by Wikiadmin on 2026-07-29. Last edited by Wikiadmin on 2026-07-29.
  1. HTML frontend tips and tricks

You can customize an AngularJS-based MDriven Turnkey frontend with HTML, CSS, and JavaScript while keeping data, business rules, and actions in your ViewModel; this page is for developers extending generated Turnkey UI.

    1. Work from the generated UI first

Turnkey uses AngularJS for ViewModel pages by default. The browser receives a UI derived from the ViewModel and binds it to the ViewModel data exposed as `root`.

For example, if your ViewModel exposes a `RegistrationNumber` column, a custom input can bind to it:

```html <input ng-model="root.RegistrationNumber" /> ```

When you replace generated markup, also preserve the ViewModel status expressions that control whether the field is enabled, visible, and styled:

```html <input ng-model="root.RegistrationNumber"

      ng-disabled="!root.VM_Status.EditOneCar_RegistrationNumber_Enabled"
      ng-show="root.VM_Status.EditOneCar_RegistrationNumber_Visible"
      ng-class="root.VM_Status.EditOneCar_RegistrationNumber_Style" />

```

Start with the standard generated UI, add CSS and small behavior changes, and replace an individual component only when needed. Replacing generated markup means you must maintain that markup when the model or ViewModel changes.

> **Keep business logic out of HTML and JavaScript.** The browser can display and update the information made available by the ViewModel, but actions and business rules belong in the model and are processed server-side. See Documentation:ViewModel for Business.

    1. Wait for dynamically rendered content

`DocumentReady` tells you that the document loaded. It does **not** guarantee that AngularJS has finished creating dynamically rendered ViewModel content.

Use an AngularJS directive when your script depends on an element created by an AngularJS loop. AngularJS calls the directive's `link` function when it creates the element, so the element is available to your code at that point.

      1. Example: initialize content in a `Channels` loop

Assume that the ViewModel exposes a `Channels` column. Add a directive attribute to the repeated element:

```html

```

Register a directive named `channel` with the Turnkey AngularJS application module. In its `link` function, run the initialization that requires the repeated element to exist.

```javascript AppModule.directive("channel", function () {

 return {
   restrict: "A",
   link: function (scope, element) {
     // The element for this channel has been created by AngularJS.
     // Run DOM-dependent initialization here.
   }
 };

}); ```

If the initialization must run once for the whole repeated set rather than once per channel, track that explicitly in the directive. For example, use a flag that you set after the first initialization.

      1. Directive timing rules

| Need | Use | Example | |---|---|---| | The document shell has loaded | Document-ready handling | Initializing code unrelated to dynamic ViewModel content | | A repeated AngularJS element has been created | An AngularJS directive `link` function | Attaching behavior to each rendered channel row | | A full generated component must be customized | Start from generated markup and verify it in browser developer tools | Replacing a grid cell while preserving its bindings |

Do not assume that document-ready handling can find elements that AngularJS renders later. Also scope your DOM lookup to the directive element where possible, rather than searching the entire document for a repeated ID.

    1. Execute a ViewModel action from custom HTML

Define the operation as an action in the ViewModel, then make the custom HTML trigger the same Turnkey client-side dispatch behavior as the generated UI.

For example, if a nested `Channels` column has an action named `SwitchChannel`, each channel can be presented as a link or button. Selecting a channel must invoke `SwitchChannel` through Turnkey's generated action dispatch, not by placing the action's business logic in JavaScript.

Use this workflow:

1. Define `SwitchChannel` as the ViewModel action that performs the channel change. 2. Generate and run the standard ViewModel UI. 3. Locate the generated control for `SwitchChannel` in browser developer tools. 4. Copy the relevant generated event/dispatch pattern into your custom link or button and retain the ViewModel context for the selected channel. 5. Test the action with multiple channel rows and confirm that the resulting ViewModel update returns to the browser.

For custom grid-row behavior, inspect the generated markup and handlers rather than guessing their names. The generated UI uses client-side dispatchers to queue events for server processing; the browser then receives ViewModel changes and AngularJS refreshes the bound UI.

      1. Gotcha: a browser click is not business logic

A custom click handler can control presentation, such as expanding a panel. It should not decide whether a channel switch is allowed, modify protected data rules, or duplicate the action implementation. Put those decisions in the model and ViewModel action so that they are consistently processed by MDrivenServer.

For the Turnkey client, the browser only has the data made available through the ViewModel. Changes and actions are sent to the server-side application, which processes business logic and access control. See MDriven Turnkey Architecture.

    1. Shorten the edit-test loop with Local TurnkeyPrototyper

You can run Turnkey locally from MDriven Designer to test changes to your model, HTML, JavaScript, and CSS without deploying the application.

1. In MDriven Designer, select the **Play** button. 2. Select **Local TurnkeyPrototyper**. 3. Confirm that IIS Express is installed before continuing. 4. Use a fresh Turnkey installation for the local prototype. 5. If your model has a sibling folder named `<YourModelName>_AssetsTK`, enable the option that copies this folder into the Turnkey installation. 6. Start the local prototype from the dialog. 7. Edit model files or files in `<YourModelName>_AssetsTK`, then run the local prototype command again to copy the asset changes into the Turnkey application and test them in Chrome or Edge.

The `_AssetsTK` folder is useful for frontend assets that must be copied alongside the model, such as CSS, JavaScript, and HTML overrides. Keep the folder next to the model and ensure that the copy option is selected; otherwise your working-folder changes are not copied to the local Turnkey installation.

    1. Scope CSS to a ViewModel

Turnkey adds the ViewModel name as a CSS class high in the page hierarchy. Use that class to avoid changing every ViewModel when you intend to style one screen.

For a ViewModel named `WorkBoard`, this rule hides the sidebar only on that ViewModel:

```css .WorkBoard #sidebar {

 visibility: hidden;

} ```

Use the existing layout selectors when styling Turnkey. For example, the AngularJS application begins under `#flexLayoutWrapper`, dynamically rendered ViewModel content is in `#contentWrapper`, and the ViewModel area is under `#viewmodelWrapper` and `#viewmodelSection`.

See Documentation:Layout and CSS for the full selector structure and Documentation:Turnkey Styling for styling guidance.

    1. Choose the right customization path

| Goal | Recommended approach | |---|---| | Change colors, spacing, or visibility for one ViewModel | Add scoped CSS, for example `.WorkBoard #sidebar` | | Bind a custom input to a ViewModel column | Use AngularJS bindings such as `ng-model="root.ColumnName"` and preserve `VM_Status` expressions | | Run code after AngularJS creates an element | Add an AngularJS directive and use its `link` function | | Replace part of the generated AngularJS UI | Start from the generated view and retain bindings, visibility, enabled, style, and action behavior | | Build MVC pages instead of AngularJS ViewModel pages | Use the MVC documentation; MVC is a separate rendering approach |

For AngularJS view replacement examples, see Documentation:Overriding AngularJS MDriven Turnkey Views. For MVC-specific behavior and generated MVC UI, see Documentation:MVC and Documentation:MVC Generated ViewModel UI in MDrivenFramework.

    1. Verify customizations in the browser

When you need to understand how Turnkey renders a control, inspect a running page with browser developer tools. Generated markup and event handlers show the binding and dispatch patterns used by the current application. This is especially important when replacing a generated control: copy the pattern you need, then test after ViewModel changes as well as after page load.

Do not replace all generated UI by default. Use generated ViewModel UI for standard cases and customize only the parts that need a distinct presentation or interaction.