Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Control content

  • Note exclude helper

...

Config string

...

Table of Contents

This library was designed to be flexible and allow total customization of the markup used by all Components.

Overriding Templates

There are three ways to replace the Handlebars template used by a component:

  • Pass a template HTML string containing a Handlebars template as described in Installation.

  • Pass the ID of a template element containing a Handlebars template as described in Installation.

  • Define the new Handlebars template as the child content of a control

Passing an HTML string

In your HTML file, define the template content directly in the configuration options:

Code Block
breakoutModewide
languagehtml
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Hawksearch Handlebars UI</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <script type="text/javascript">
      var Hawksearch = Hawksearch || {};

      Hawksearch.config = {
        clientId: "f51060e1c38446f0bacdf283390c37e8",
        templates: {
          pageSize: `
            <div class='page-size'>
              <select hawksearch-page-size>
                {{#each options}}
                  <option value='{{pageSize}}' {{attribute 'selected' selected}}>{{title}}</option>
                {{/each}}
              </select>
            </div>`
        }
      };
    </script>
    <script src="node_modules/@bridgeline-digital/hawksearch-handlebars-ui/dist/handlebars-ui.js" defer ></script>
  </head>

  <body>
    <h1>Hawksearch Handlebars UI</h1>
    <hawksearch-search></hawksearch-search>
    <hawksearch-results></hawksearch-results>
  </body>
</html>

Creating a template element

In your HTML file, add the custom markup to a template element and pass the ID in the configuration options:

Code Block
breakoutModewide
languagehtml
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Hawksearch Handlebars UI</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <script type="text/javascript">
      var Hawksearch = Hawksearch || {};

      Hawksearch.config = {
        clientId: "f51060e1c38446f0bacdf283390c37e8",
        templates: {
            pageSize:'page-size-template'
        }
      };
    </script>
    <script src="node_modules/@bridgeline-digital/hawksearch-handlebars-ui/dist/handlebars-ui.js" defer ></script>
  </head>

  <body>
    <h1>Hawksearch Handlebars UI</h1>
    <hawksearch-search></hawksearch-search>
    <hawksearch-results></hawksearch-results>
    <template id="page-size-template">
      <div class='page-size'>
        <select hawksearch-page-size>
          {{#each options}}
            <option value='{{pageSize}}' {{attribute 'selected' selected}}>{{title}}</option>
          {{/each}}
        </select>
      </div>
    </template>
  </body>
</html>
Info

This approach tends to be easier to manage than the previous option as it is more compatible with popular HTML editors and templates can potentially be loaded from separate files using Server-side Includes (SSI).

Setting control content

Code Block
languagehtml
<hawksearch-page-size>
  <div class='page-size'>
    <select hawksearch-page-size>
      {{#each options}}
        <option value='{{pageSize}}' {{attribute 'selected' selected}}>{{title}}</option>
      {{/each}}
    </select>
  </div>
</hawksearch-page-size>
Info

This approach is simplest only if you place all of the components manually and avoid using the Search Results Component as that wraps around most of the other components.

Note

If you choose this approach to customization and need to define a template for a nested element, be aware that by default, Handlebars will try to apply the model from the top-level component to all nested components, which will not work. To guard against this behavior, use the exclude helper documented in Handlebars Helpers.

Handlebars Helpers

Default Templates

The following helper functions are available in this library by default:

add

This function returns the sum of two values:

Code Block
languagetypescript
Hawksearch.handlebars.registerHelper('add', function (value1: number, value2: number): number {
    return value1 + value2;
});

and

This function returns whether or not all passed arguments resolve to true:

Code Block
languagetypescript
Hawksearch.handlebars.registerHelper('and', function (...values: Array<any>): boolean {
    return values.slice(0, -1).every((v) => !!v); // Omit last argument as that is the Handlebars options function
});

attribute

This function renders an attribute or attribute value if the given condition resolves to true:

Code Block
languagetypescript
Hawksearch.handlebars.registerHelper('attribute', function (attribute: string, condition: any): string {
    return condition ? attribute : '';
});

concat

This function combines multiple values into a single string:

Code Block
languagetypescript
Hawksearch.handlebars.registerHelper('concat', function (...values: Array<any>): string {
    if (values.length < 2) {
        return '';
    }

    return values.slice(0, -1).join(''); // Omit last argument as that is the Handlebars options function
});

currency

This function formats a value as currency:

Code Block
languagetypescript
Hawksearch.handlebars.registerHelper('currency', (value: number | Array<number> | undefined, decimals: number, defaultValue?: number): string | undefined => {
    if (typeof defaultValue === 'object') {
        defaultValue = undefined;
    }

    if (value instanceof Array) {
        value = value[0];
    }

    return formatCurrency(value ?? defaultValue ?? 0, decimals);
});

eq

This function returns whether two values are equivalent:

Code Block
languagetypescript
Hawksearch.handlebars.registerHelper('eq', function (value1: any, value2: any): boolean {
    return value1 === value2;
});

exclude

This function is used to prevent Handlebars from attempting to bind a data model to a nested control containing a custom template:

Code Block
languagetypescript
Hawksearch.handlebars.registerHelper('eq', function (value1: any, value2: any): boolean {
    return value1 === value2;
});

To better illustrate, see the following example:

Code Block
languagehtml
<hawksearch-results>
    {{{{exclude}}}}
        <hawksearch-pagination>
            {{#if displayFirstLink}}
                <a hawksearch-page="1">First</a>
            {{/if}}
            {{#if displayLastLink}}
                <a hawksearch-page="{{totalPages}}">Last</a>
            {{/if}}
        </hawksearch-pagination>
    {{{{/exclude}}}}
</hawksearch-results>

html

This function is used to render a provided string as HTML rather than escape special characters:

Code Block
languagetypescript
Hawksearch.handlebars.registerHelper('html', function (html: string): Handlebars.SafeString {
    return new Hawksearch.handlebars.SafeString(html);
});
Note

This should only be used to bind values from trusted sources.

if-else

This function is used to render different content inline depending on whether a condition resolves to true or false:

Code Block
languagetypescript
Hawksearch.handlebars.registerHelper('if-else', function (condition: any, trueValue: any, falseValue: any): any {
    return condition ? trueValue : falseValue;
});

lt

This function returns whether the first provided value is less than the second provided value:

Code Block
languagetypescript
Hawksearch.handlebars.registerHelper('lt', function (value1: any, value2: any): boolean {
    return value1 < value2;
});

lte

This function returns whether the first provided value is less than or equal to the second provided value:

Code Block
languagetypescript
Hawksearch.handlebars.registerHelper('lte', function (value1: any, value2: any): boolean {
    return value1 <= value2;
});

gt

This function returns whether the first provided value is greater than the second provided value:

Code Block
languagetypescript
Hawksearch.handlebars.registerHelper('gt', function (value1: any, value2: any): boolean {
    return value1 > value2;
});

gte

This function returns whether the first provided value is greater than or equal to the second provided value:

Code Block
languagetypescript
Hawksearch.handlebars.registerHelper('gte', function (value1: any, value2: any): boolean {
    return value1 >= value2;
});

number

This function formats a number:

Code Block
languagetypescript
Hawksearch.handlebars.registerHelper('number', (value: number | Array<number> | undefined, decimals: number, defaultValue?: number): string | undefined => {
    if (typeof defaultValue === 'object') {
        defaultValue = undefined;
    }

    if (value instanceof Array) {
        value = value[0];
    }

    return formatNumber(value ?? defaultValue ?? 0, decimals);
});

or

This function returns whether either provided value resolves to true:

Code Block
languagetypescript
Hawksearch.handlebars.registerHelper('or', function (...values: Array<any>): boolean {
    return values.slice(0, -1).some((v) => !!v); // Omit last argument as that is the Handlebars options function
});

string

This function displays a specified string with an optional default value:

Code Block
languagetypescript
Hawksearch.handlebars.registerHelper('string', (value: string | Array<string> | undefined, defaultValue?: string): string | undefined => {
    if (typeof defaultValue === 'object') {
        defaultValue = undefined;
    }

    if (value instanceof Array) {
        value = value[0];
    }

    return value ?? defaultValue;
});
Info

This is most likely to be used in the context of the Search Results Item Component.

subtract

This function returns the difference of two values:

Code Block
languagetypescript
Hawksearch.handlebars.registerHelper('subtract', function (value1: number, value2: number): number {
    return value1 - value2;
});

Custom Templates

The Handlebars instance is exposed via Hawksearch.handlebars. You can use this reference to define your own helper functions as needed.

Info

For more information, see Global Models.