Comparison operators in Ember Handlebar files

I have a file ifCond.js, in which I have bunch of helper functions, but I am concerned with mainly two functions log (which logs in values in hbs file) and IMS.ConditionHelper, I am not able to use IMS.ConditionHelper why, I want to use this function for that purpose, how can I do it - any help please? Here is my ifCond.js code:

export default () => {
    var log = function (data) {
        console.log(data);
    }
    var log = Ember.assign(log, {
        print: function (style, message) {
            var template = "";
            style.forEach(function (item) {
                if (typeof item == 'object') {
                    for (var prop in item) {
                        template += prop + ":" + item[prop] + ";";
                    }
                } else {
                    var style = log.styles[item];
                    if (style)
                        for (var prop in style) {
                            template += prop + ":" + style[prop] + ";";
                        }
                }
            })
        },
        styles: {
            title: {
                'font-size': '30px',
            },
            italic: {
                'font-style': 'italic'
            },
            bold: {
                'font-weight': 'bold'
            },
            underline: {
                'text-decoration': 'underline'
            },
            success: {
                'color': '#23aa15'
            },
            error: {
                'color': '#ee3619'
            },
            attention: {
                'color': '#ee339e'
            }
        }
    });

     IMS.ConditionHelper = Ember.Helper.extend({
        compute: function (args) {
            var v1 = args[0],
                operator = args[1],
                v2 = args[2];
            if (v1 === undefined || v2 === undefined) {
                console.warn("Condition BoundHelper received undefined value");
                return false;
            }
            switch (operator) {
                case '!=':
                    return (v1 != v2) ? true : false;
                case '==':
                    return (v1 == v2) ? true : false;
                case '===':
                    return (v1 === v2) ? true : false;
                case '<':
                    return (v1 < v2) ? true : false;
                case '<=':
                    return (v1 <= v2) ? true : false;
                case '>':
                    return (v1 > v2) ? true : false;
                case '>=':
                    return (v1 >= v2) ? true : false;
                case '&&':
                    return (v1 && v2) ? true : false;
                case '||':
                    return (v1 || v2) ? true : false;
                default:
                    return false;
            }
        }
})
}

How can I use ā€œIMS.ConditionHelperā€ in Handlebars, if I call it directly {{#if (IMS.ConditionHelper ā€˜1ā€™ ā€˜===ā€™ ā€˜1ā€™)}} True {{/if}} - throwing me error. Any help, I want a conditional operator - any help would be very very helpful - thanks in advance. I am not sure if I am using Ember-cli or Ember webpack but application is working except this ConditionHelper function being called in the Handlebar file - any help would be greatly helpful - thanks in advance

Hi, @abdul. Thanks for asking us for help.

I took a glance at your code for compute in IMS.ConditionHelper. While I didnā€™t fully understand your helper code (in particular, how your export works), from your template example that you wanted to achieve,

{{#if (IMS.ConditionHelper ā€˜1ā€™ ā€˜===ā€™ ā€˜1ā€™)}}
    True
{{/if}}

it seemed to me like the Ember addon called Ember Truth Helpers would solve your problem.

After installing this addon by running ember install ember-truth-helpers in your terminal, you would write in your template,

{{#if (eq ā€˜1ā€™ ā€˜1ā€™)}}
    True
{{/if}}

Let us know if this is what you wanted? Thanks!

1 Like

Oohā€¦ I missed your other thread about being unable to install the addon. My bad.

1 Like

Some how I have to make it working my friend, I am tired, trying trying I donā€™t know what to do, I donā€™t have time for upgrading the whole app and I am not able to use if else conditions etc on objects - any help would be greatly helpful my friend.

Sorry to hear about the difficulties you faced with the custom project. As I havenā€™t worked with a custom project before, I can only make a guess at the solution here.

Iā€™d first try simplifying the problem. Your code shows doing many things (log, styles, compute). I think tackling one problem at a time (letā€™s get the equal operator working first!) may help you figure out what you need to do in your project.

In a typical Ember project, a template helper file looks like this. (I saw Ember 3.13.2 in your other thread so Iā€™m assuming that you can use the following import syntax.)

// This code lives in app/helpers/eq.js
import { helper } from '@ember/component/helper';

export default helper(function eq(params) {
    return params[0] === params[1];
});

I named the helper eq in order to match the name used by Ember Truth Helpers. That way, if you do figure out how to install the addon, you could remove your eq helper and the app would run the same.

The template, which uses the helper, might look like this:

{{#if (eq "0" "0")}}
    Case 1
{{/if}}

{{#if (eq "0" 0)}}
    Case 2
{{/if}}

{{#if (eq "0" false)}}
    Case 3
{{/if}}

Since I used === for comparison, only the text Case 1 will show up on the webpage. If you use == instead, all 3 texts will show up. Once you verify that the page handles the helper correctly, you could then add validations (and rendering tests if you have time) to the helper.

1 Like

If I use it my application is throwing error saying unable to find module @ember/component/helper

Right now Iā€™m going to go to work Iā€™ll try it in an hour

I am getting the following error when I use it, what can I do?

If you canā€™t get imports working, there is probably something broken in your custom build setup. But there may be a quick workaround. Instead of

import { helper } from '@ember/component/helper';

Try this:

var helper = Ember.Helper.helper;

That should work because thereā€™s an older pre-imports API that still exists.

1 Like

Some other helper functions are working like for example money.js which is written in the following way, but when I create comparer.js file the same way that money.js exists and tried to use it, then still it gives me error saying comparer is not a helper function, money.js contains code as below:

export default () => { 
IMS.MoneyHelper = Ember.Helper.extend({
    compute: function (args, options) {
        console.log('Money from /ember');
        var value=args[0];
        var value = parseFloat(value);
        value = options.neg | options.negative | options.minus ? -value : value;
        var format = value < 0 ? '($#)' : '$#';
        var ret = value.toLocaleString();
        if (ret.indexOf('.') != -1)
            ret = ret.split('.')[1].length == 1 ? ret + '0' : ret;
        return format.replace('#', ret.replace('', ''));
    }
}) 
 }

And my comparer.js file code is as below:

export default () => {
    IMS.MoneyHelper = Ember.Helper.extend({
        compute: function (args) {
            console.log('comparer from /ember');
            var v1 = args[0],
                operator = args[1],
                v2 = args[2];
            if (v1 === undefined || v2 === undefined) {
                console.warn("Condition BoundHelper received undefined value");
                return false;
            }
            switch (operator) {
                case '!=':
                    return (v1 != v2) ? true : false;
                case '==':
                    return (v1 == v2) ? true : false;
                case '===':
                    return (v1 === v2) ? true : false;
                case '<':
                    return (v1 < v2) ? true : false;
                case '<=':
                    return (v1 <= v2) ? true : false;
                case '>':
                    return (v1 > v2) ? true : false;
                case '>=':
                    return (v1 >= v2) ? true : false;
                case '&&':
                    return (v1 && v2) ? true : false;
                case '||':
                    return (v1 || v2) ? true : false;
                default:
                    return false;
            }
        }
    })
}

When I am able to use money the following way: {{money 10000000}} Why am I not able to use comparer in the following way in my handlebar

                {{#if (comparer 'complete' '==' 'complete')}}
                {{log 'Complete'}}
                {{/if}}

Any help please why is it not working thank you.

Based on the webpack config you shared in the other thread, I would search for the name of the working helper file in all your other files to see how theyā€™re importing it into the build. Then you need to do that same thing for your new helper file.

1 Like

The part of the problem is, he has created the money.js file in multiple places and when I put the console.log, it seems that he is using the money.js file which is in ./helpers/ember folder, but he has function under ./helpers/print folder too. Here is my webpack.config,js file, from which it seems the helper functions are taken from the .helpers/ember folder but still let me know if I have to change something. Do I need to register this new helper function within Handlebars or controllers or some other place, any help buddy?

const path = require('path');
require('./.webpack/build-includes');

module.exports = {
    entry: {
        polyfill: 'babel-polyfill',
        libs: './.webpack/webpack-entry-dev.js',
        templates: './.webpack/webpack-templates.js',
        app: './.webpack/webpack-app.js',
    },
    cache: true,
    devtool: 'inline-source-map',
    output: {
        filename: '[name].js',
        path: path.resolve('../IMS.Web/Ember/dist'),
        publicPath: 'public'
    },
    resolve: {
        alias: {
            app: path.resolve('./app'),
            helpers: path.resolve('./helpers/ember'),
            styles: path.resolve('./CSS'),
            libs: path.resolve('./libs')
        },
        extensions: ['.hbs', '.js', '.less']
    },
    module: {
        rules: [{
            test: /\.js$/,
            exclude: /(node_modules|bower_components)/,
            use: {
                loader: 'babel-loader',
                options: {
                    presets: ['@babel/preset-env']
                }
            }
        }, {
            test: /\.hbs$/,
            loader: path.resolve(__dirname, `.webpack/webpack-handlebars`),
            options: {
                sourceMap: true
            }
        }, {
            test: /\.(less)$/,
            use: [{
                    loader: 'style-loader',
                    options: {
                        injectType: 'singletonStyleTag'
                    }
                },
                {
                    loader: 'css-loader',
                    options: {
                        sourceMap: true
                    }
                },
                {
                    loader: 'less-loader',
                    options: {
                        sourceMap: true
                    }
                }
            ],
        }, 
        {
            test: /\.(scss|sass)$/,
            use: [{
                    loader: 'style-loader',
                    options: {
                        sourceMap: true
                    }
                },
                {
                    loader: 'css-loader',
                    options: {
                        sourceMap: true
                    }
                },
                {
                    loader: 'sass-loader',
                    options: {
                        sourceMap: true
                    }
                }
            ],
        }, 
        {
            test: /\.(woff|woff2|eot|ttf|jpg|jpeg|png|svg|gif)$/,
            use: [{
                loader: 'file-loader',
                options: {
                    name: '[name].[ext]',
                    publicPath: 'Ember/dist'
                },
            }],
        }],
    },
    mode: 'none'
}

Any help would be felt happiest, thank you so much for your support my friend.

The ā€œregisterā€ part is probably going to be some code that says define(. Look for that.

1 Like

Which register? Register in Handlebars or controllers? Can you please elaborate my friend?

I was quoting you when you said ā€œregisterā€:

I donā€™t know where this app puts the actual define, because itā€™s normally not something youā€™d have to write by hand at all. Thatā€™s why Iā€™m saying you should run a search for define( to see where itā€™s already being used. My bet is that you will find it. If you donā€™t, that would also be interesting and we can dig in further.

1 Like

Not the define, but I saw a file named build-includes.js under .webpack folder in my Ember project, that file is using something like this:

    /**
 * Joind Files 
 */
   async __parts() {
    let files = await this.files();
    let helpers = await this.helpers();

    let text = "";

    text += `// Add Collectors\r\n`;
    text += `Ember.appFiles = [\r\n`;
    text += `    // Ember Controller/Comonents/Routes/etc...\r\n`;
    files.forEach(file => text += `    ${file}\r\n`)

    text += `    // Helpers\r\n`;
    helpers.forEach(file => text += `    ${file}\r\n`)

    text += `]`;

    fs.writeFileSync('./.webpack/webpack-results.js', text);
}

And the following function to create helper functions:

/** 
 *  Helpers: 
 */
async helpers() {
    return new Promise(resolve => {
        let includes = [];
        glob('./helpers/ember/**/*.js', {}, (err, data) => {
            data.forEach(file => {
                file = file.replace('./', '');
                file = file.replace('helpers/ember', 'helpers');
                console.log(file);
                includes.push(`require("${file}"),`);
            });
            resolve(includes);
        });
    })
}

When I console.log ed, it shows my helper functions js file, it means the function is being exported, so is this export only for Production, do I need to make any changes for it to make available for development also or what am I missing that I am getting error saying its not a helper function - but why is money.js, log.js are working properly? Any help my friend.

Did it my friend, its done. Here it is, the previous developer put all the helper functions in one file, the confusion he created was, he put other files with those helper functions in different directories - it seems I need to clean that up. And your suggestion to check the define helped me to look into the webpack.config.js (async helpers, async __parts), there he is combining all the files scripts and generating as one js file which is written on to app.js. The convention he (or Ember I am not sure) followed was camel casing. For example for one helper-function he written as below withing the same ifCond.js file, is converted as ā€œreplaceā€, we can use it as replace in handlebar

IMS.ReplaceHelper = Ember.Helper.extend({
    compute(args) {
        return args[0].replace(new RegExp(args[1], 'ig'), args[2]);
    }
})

If suppose, if there are two Words - then it follows the camel casing (you know it). Totally completed and I have written some helper functions of my own as needed - thanks a lot for everybody who jumped-in to help me - thanks a lot and I donā€™t have words how to describe how happy I am - thank you. My own helper functions as below:

    IMS.IsLastHelper = Ember.Helper.extend({
        compute(args) {
            var list = args[0];
            var item = args[1];

        if (Array.isArray(list)) {
            var id = list.indexOf(item);
            return id == list.length - 1;
        }
        return false;
    }
})
IMS.IsFirstHelper = Ember.Helper.extend({
    compute(args) {
        var list = args[0];
        var item = args[1];

        if (Array.isArray(list)) {
            var id = list.indexOf(item);
            return id == 0;
        }
        return false;
    }
})

And I called them with syntax as below:

                        {{#each  model.novs as |nov index|}}
                        {{#if (isFirst model.novs nov)}}
                        ({{nov.NOVNumber}}:
                        {{else}}
                        {{nov.NOVNumber}}:
                        {{/if}}
                        {{#each  nov.Violations as |novv index|}}
                        {{#unless (isLast nov.Violations novv)}}
                        {{novv.ViolationNumber}},
                        {{else}}
                        {{#if (isLast model.novs nov)}}
                        {{novv.ViolationNumber}}
                        {{else}}
                        {{novv.ViolationNumber}};
                        {{/if}}
                        {{/unless}}
                        {{/each}}
                        {{#if (isLast model.novs nov)}}
                        )
                        {{/if}}
                        {{/each}}

Thanks again to everybody in this group. :pray: