how to add hbs file inside master hbs file in sugarcrm


My goal is to show multiple pages like wizard inside a popup in sugarcrm . solution i seems is to added partial .hbs file inside master hbs file .

i have gone through documentation

  1. Create a Handlebars helper file
`(function(app) {"app:init", function() {

        Handlebars.registerHelper("customUpperCase", function (text)
            return text.toUpperCase();

  1. create a JSGrouping extension
`foreach($js_groupings as $key => $groupings) {
    foreach($groupings as $file => $target) {
        if ($target == 'include/javascript/sugar_grp7.min.js') {
            //append the custom helper file
            $js_groupings[$key]['custom/JavaScript/my-handlebar-helpers.js'] = 'include/javascript/sugar_grp7.min.js';

  1. use your custom helpers in the HBS files by using:
  {{customUpperCase "MyString"}} `

But this is not working , and it only passing string in hbs file , i want to add full html or php page in hbs

i also tried iframe or include 'example.php' in hbs file , but it hangs in sugarcrm . what is correct way to add multiple child pages in one hbs file

  • What is "not working"? What does it do?

    Do you mean you want to have an hbs file you can call multiple times from another hbs file? This is called "partial".

    I have a report hbs with a number of "sections" each of which calls another hbs file to render that section.


    {{#if catData}}
    {{#with catData}}
        {{partial 'relationship' ../this a01_properties_contacts_7 ../options}}
        {{partial 'relate' ../this cpad ../options}}
        {{partial 'relationship' ../this a01_properties_contacts_6 ../options}}

    relationship.hbs in same folder

    <div class="row-fluid record-panel">
            <div class="row-fluid record-panel-header-container panel-active">
                <span class="record-panel-header">
                    <span>{{title}} ({{count}})</span>
    {{#if has_content}}
            <div class="row-fluid record-panel-content">
                <div class="list-view">
                    <table class="table table-striped dataTable">
        {{#each header}}
         {{#each rows}}
            {{#each this}}
                                <td><span class="overflow-visible" style="white-space: normal;">
                {{#if (equals @key "id")}}
                                    <a href="#{{../../../module}}/{{this}}" target="_blank">[link]</a>

    (that (equals) is a custom hbs helper to compare two values, NOT the same as the sugar "eq" helper)

    cat.js again in same folder

        extendsFrom: 'BaseView',
        className: 'catreport',
        initialize: function(options) {
            this._super('initialize', [options]);
            this.catData = {};
    console.log('cat initialize',;
        /* */
        loadData: function(options) {
    //console.log('cat loadData',options);
            let self = this;
  'cat_loading', {level: 'process', title: app.lang.get('LBL_LOADING')});
  "read", app.api.buildURL('Contacts/''/cat'), null, {
                success: function (data) {
    //console.log('cat loadData success',data);
                    self.catData = data;
                error: function(data) {
                    app.error.handleHttpError(data, {});
        _loadTemplate: function() {
    //console.log('cat _loadTemplate');
            this.action = 'detail'; // not 'cat'
            this.options = {
                data: {},
                hash: {}
        _render: function () {
            // this gets called TWICE: once BEFORE data loaded, then once AFTER (load success)
    //console.log('cat _render');

    This calls the API to get the data to display, then calls render()

    this.catData is the object of data passed to cat.hbs

    this.options is required by the partial hbs helper, not sure what this is for but needs to exist.

    In cat.hbs, catData is used to render.