0
votes

I have created a table/grid using jsViews. Each row has an edit button which when clicked selects the row and shows input controls instead of text values.

If I show/hide the inputs using data-link="visible{:#parent.parent.data.selectedIndex!==#index}" then it works fine.

However, I was trying a different approach using {^{if #parent.parent.data.selectedIndex===#index}}...{{else}}...{{/if}} to show/hide the inputs and this doesn't work when selectedIndex changes on my data object.

I also tried with {^{if ~root.selectedIndex===#index}} but that didn't work either. Is it possible to do this with {{if}}? The reason I am trying this over the first method that worked was to avoid rendering lots of select boxes which will just be hidden anyway.

My data object looks like this:

app = {
    data: [...],

    selectedIndex: null,

    select: function select(index) {
        if (this.selectedIndex !== index) {
            $.observable(this).setProperty("selectedIndex", index);
        }
    }
};

I link the template like this:

$.templates("#myTemplate").link("#divHolder", app)
    .on("click", ".data .editButton", function() {
        app.select($.view(this).index);
    })
    .on("click", ".data .saveButton", function() {
        // save details
    })
    .on("click", ".transmittals .cancelButton", function() {
        // reset values

        app.select(null);
    });

My template is like this:

<script id="myTemplate" type="text/x-jsrender">
    <table id="tblData" class="data">
        <thead>
            <tr>
                <th></th>
                <th>A</th>
                <th>B</th>
                <th>C</th>                    
            </tr>
        </thead>
        <tbody>
            {^{for data}}
            <tr class="item">
                <td>
                    {{if #parent.parent.data.selectedIndex===#index}}
            <span class="editItem">
                <button class="cancelButton">Cancel</button></span>
                    {{else}}
            <span class="viewItem">
                <button class="editButton">Edit</button></span>
                    {{/if}}                
                </td>
                <td>
                    {^{if #parent.parent.data.selectedIndex===#index}}
            <span class="editItem"><input type="text" data-link="B" /></span>
                    {{else}}
            <span class="viewItem" data-link="B"></span>
                    {{/if}}
                </td>
                <td>
                    {^{if #parent.parent.data.selectedIndex===#index}}
            <span class="editItem"><input type="text" data-link="C" /></span>
                    {{else}}
            <span class="viewItem" data-link="C"></span>
                    {{/if}}
                </td>
            </tr>
        {{/for}}
        </tbody>
    </table>
</script>
1

1 Answers

1
votes

When you add an {{if}} block, it is a nested view, so the button click is not getting you the item view with the index. You need to use $.view(this).parent.index - or, simpler, $.view(this).getIndex() - which automatically steps up through nested views (if any) to the item view and gets its index.

app.select($.view(this).getIndex());

(See discussion here: https://github.com/BorisMoore/jsrender/issues/173#issuecomment-11058106)

BTW here is a modified form of your sample, just to give you some ideas. It uses <button data-link="{on ~root.select #getIndex()}">Edit</button> to hook up the click handler on the button and call the select method directly, passing it the index:

<script id="myTemplate" type="text/x-jsrender">
<table id="tblData" class="data">
    <thead>
        ...
    </thead>
    <tbody>
    {^{for data}}
        <tr class="item">
        {^{if ~root.selectedIndex===#index}}
            <td><button class="cancelButton" data-link="{on ~root.select null}">Cancel</button></td>
            <td><input data-link="A" /></td>
            <td><input data-link="B" /></td>
        {{else}}
            <td><button class="editButton" data-link="{on ~root.select #getIndex()}">Edit</button></td>
            <td data-link="A"></td>
            <td data-link="B"></td>
        {{/if}}
        </tr>
    {{/for}}
    </tbody>
</table>
</script>

<div id="divHolder"></div>

<script>
var app = {
    data: [{A:"aa", B: "bb"},{A:"aa2", B: "bb2"}],
    selectedIndex: null,
    select: function(index) {
        if (this.selectedIndex !== index) {
            $.observable(this).setProperty("selectedIndex", index);
        }
    }
};

$.templates("#myTemplate").link("#divHolder", app);
</script>