Search code examples
knockout.jshtml-listsdevextreme

Access list elements with knockout


I have a list with 2 images per line, after filling the list with my datasource, I need to set one of the images with "visible = false" depending on the user's choice, I am not able to access the list elements to set one of the images = false

list html

            <div data-bind="dxList: {items: listItems, dataSource: AdataSource, pullRefreshEnabled: true }" id="lxDados">
            <div data-options="dxTemplate : { name: 'item' } " id="dxtemp">

                <div class="us-linha-img">
                    <span class="dx-icon-map icon us-itens-linha"></span>
                    <span class="us-itens-linha" data-bind="text: evento"></span>
                </div>

                <img id="imcodb" data-bind="attr: { src: $data.codbar, alt: $data.codbar }" />
                <br />
                <img id="imcodbqr" data-bind="attr: { src: $data.codbarqr, alt: $data.codbar }" />

            </div>
        </div>

js file In this function, after loading the list with my datasource, I need to scroll through the list and set one of the "img" to visible = true or false.

function trocarCodBar(m) {
AdataSource = loadDataSource();
viewModel.AdataSource(AdataSource);
//done...
for (var i = 0; i < viewModel.listItems().length; i++) {
    if(m=='bar')
    //set <img imcodb or imcodbqr visible false or true.
}}

view

var viewModel = {
bloadpanel: ko.observable(false),
AdataSource: null,
listItems: ko.observableArray(),
trocarCodBarBar: function () {
    trocarCodBar("bar");
},
trocarCodBarQR: function () {
    trocarCodBar("qrc");
},
viewShown: function () {
    //alterar valores na inicialização
},
title: ko.observable("Pedido: " + params.id)};
viewModel.AdataSource = AdataSource;
return viewModel;

Solution

  • It isn't a good practice to use html elements inside a knockout view model. Just use ko.observable to manage a dynamic rendering.

    First of all, create the observables fields within your data set like below:

    vm.dataSource = ko.observableArray([
        { text: "a", firstImageVisible: ko.observable(true), secondImageVisible: ko.observable(false) },
        { text: "b", firstImageVisible: ko.observable(true), secondImageVisible: ko.observable(false) },
        { text: "c", firstImageVisible: ko.observable(true), secondImageVisible: ko.observable(false) }
    ]);
    

    In your case there are two ways to change image visibility.

    The first one is the visible binding:

    <img data-bind="attr: { src: '...' }, visible: firstImageVisible "/>
    <img data-bind="attr: { src: '...' }, visible: secondImageVisible "/>
    

    https://jsfiddle.net/ofbugahL/

    The second way is the if binding:

    <!-- ko if: firstImageVisible -->
    <img data-bind="attr: { src: '...' } "/>
    <!-- /ko -->
    
    <!-- ko if: secondImageVisible -->
    <img data-bind="attr: { src: '...' } "/>
    <!-- /ko -->
    

    https://jsfiddle.net/0nkju2Lz/

    Next, if you want to show the first image, just set the firstImageVisible field to true and the secondImageVisible field to false. Knockout automatically updates your list.