LCJ
LCJ

Reputation: 22652

How to add button with icon inside jqGrid Formatter

I tried to add a button inside a jqGrid column, with an icon – but it is coming as undefined. What is the correct way to do this?

enter image description here

CODE

colModel: [
    { name: 'RoleID', index: 'RoleID', width: 100 },
    { name: 'RoleName', index: 'RoleName', width: 250 },
    { name: 'RoleRequestedDate', index: 'RoleRequestedDate', formatter: 'date', formatoptions: { srcformat: 'm/d/Y', newformat: 'm/d/Y' }, width: 125 },
    { name: 'RoleApprovedDate', index: 'RoleApprovedDate', formatter: 'date', formatoptions: { srcformat: 'm/d/Y', newformat: 'm/d/Y' }, width: 125 },

    {
        name: 'Request', index: 'RoleID', width: 120,
        formatter: function (cellvalue, options, rowObject) {
            //return '<span class="ui-icon ui-icon-circle-plus app-custom-button-create"  title="Create";"></span>';
            if (rowObject["UserRoleID"] == "0") {
                if (rowObject["RoleRequestID"] == "0") {
                    //return '<span class="ui-icon ui-icon-circle-plus app-custom-button-request"  title="Request";"></span>';
                    //return '<button id="btnRequest" class="ui-icon ui-icon-circle-plus app-custom-button-request"  type="submit" return false;>Request</button>';

                    return 
                            '<button class="ui-button ui-widget ui-state-default">' +
                            '<span class="ui-button-icon-primary ui-icon ui-icon-star">Request</span>' +
                            '</button>';

                }
                else {
                    return '<span class="ui-icon ui-icon-folder-collapsed"  title="Already Requested";"></span>';
                }

            }
            else {
                return '<span class="ui-icon ui-icon-check"  title="Has Role";"></span>';
            }
        }
    }

],

Upvotes: 0

Views: 1408

Answers (1)

Oleg
Oleg

Reputation: 221997

It looks that your main computer language is C# and you try to use JavaScript in the same style like you write your C# program. It's an important error! You create in the way the code which looks correct, but it works in the wrong way. I developed many years before the code in C/C++/C# and many other non-C-like languages. So I did the same errors like you. Only after understanding that JavaScript have absolutely another semantic I changed my style for JavaScript programs and all become good.

Back to your code. You wrote the statement

return 
    '<button class="ui-button ui-widget ui-state-default">' +
    '<span class="ui-button-icon-primary ui-icon ui-icon-star">Request</span>' +
    '</button>';

which looks correctly, and it would be correctly in C#, but it will be interpreted as the following in JavaScript:

return;
'<button class="ui-button ui-widget ui-state-default">' +
'<span class="ui-button-icon-primary ui-icon ui-icon-star">Request</span>' +
'</button>';

So you have two statements because of auto-inserting of semicolon. The first line return undefined and the second like will be never executed at all and it will be removed it you would minimize your JavaScript code.

I strictly recommend you to use the following simple rule: if you need to continue the statement on another line you should end the line with the part of the symbol like + or { or any other which can't be as the last symbol of the statement. You should not know exactly all rules of auto-inserting of semicolon. The rules will be never works in the case at all.

In your case you need just write

return '<button class="ui-button ui-widget ui-state-default">' +
    '<span class="ui-button-icon-primary ui-icon ui-icon-star">Request</span>' +
    '</button>';

By the way I personally prefer to use " in strings and use ' inside of string. The rule is a little better because the same rule hold the most JavaScript frameworks/libraries.

The next example from your code: you use the line

if (rowObject["UserRoleID"] == "0") {
    ...

The main problem here is the usage of equality operator ==, typical for C#, instead of strict equality operator === which is strictly recommended to use in JavaScript. The problem is that the code which use == looks not like it do in reality. JavaScript uses type conversion in case of == usage which can produce very strange effects. For example 0 == "0" is true and false == "0" is true. It's not what one want in the most cases. The classical example which shows how dangerous is the operator ==: 0 == '' is true and 0 == '0' is true, but '' == '0' is of cause false. So the usage of == can easy break the main mathematical rules.

More simple and non-critical changes which I recommend you to do is the usage of rowObject.UserRoleID instead of rowObject["UserRoleID"]. You should use ["..."] syntax only with variables or if you use the properties which contains either special characters like rowObject["User.Role.ID"] or rowObject["User Role ID"] or it the property name is reserved word in some JavaScript dialect like rowObject["class"] or rowObject["if"].

The next remark: you should verify the quotes (") in the strings '... title="Has Role";"></span>' and '... title="Already Requested";"></span>';. The part ;" should be probebly removed.

Finally, small remarks specific for jqGrid. First of all I recommend you to remove unneeded index property from colModel. You will have the same results after removing of index, but your code will be shorter and easy to read. The next advice: you should consider to add key: true to the column RoleID if it contains unique values. It informs jqGrid to use the values as rowids (the values for id attribute of <tr> elements).

The last remark: you should confider to use column templates. In simplest form you can define the object

var myDateTemplate = { formatter: 'date',
        formatoptions: { srcformat: 'm/d/Y', newformat: 'm/d/Y' }, width: 125 };

somewhere above the code which creates jqGrid and to define RoleRequestedDate and RoleApprovedDate as the following

{ name: 'RoleRequestedDate', template: myDateTemplate },
{ name: 'RoleApprovedDate', template: myDateTemplate },

It reduces your code, makes it more readable and easy to maintain. See here or here for more information about column templates.

Upvotes: 1

Related Questions