jQuery UI Widgets Forums Plugins AngularJS jqxgrid refreshing while !ng-show with filterrow -> JS error

This topic contains 3 replies, has 2 voices, and was last updated by  Dimitar 8 years, 10 months ago.

Viewing 4 posts - 1 through 4 (of 4 total)
  • Author

  • badera
    Participant

    Dear all

    I encountered problems (JS exceptions), if I have a jqx-grid inside a <div>, which is sometimes hidden and sometimes shown (with ng-show) and the grid is refreshed (sometimes in the hidden state.)

    I traced down the problem and remarked, that this only happens, if showfilterrow: true. The example below (based on your angularjs-grid-refresh.htm) lets reproduce the problem (of course, this simple sample does not make sence on its own – but it shows the actual JS exception I also get on my real project and in such scenarios, the grid displays the unrefreshed (old) data -> this is the real problem in this case).

    To reproduce it, click “Hide Grid”, then click at least two times on “Refresh Source” -> The JS exception is thrown.

    <!DOCTYPE html>
    <html ng-app="demoApp">
    <head>
        <title id="Description">AngularJS Grid directive. Refresh Source</title>
        <link rel="stylesheet" type="text/css" href="../../../jqwidgets/styles/jqx.base.css" />
        <script type="text/javascript" src="../../../scripts/angular.min.js"></script>
        <script type="text/javascript" src="../../../scripts/jquery-1.11.1.min.js"></script>
        <script type="text/javascript" src="../../../jqwidgets/jqx-all.js"></script>
        <script type="text/javascript" src="../../../scripts/demos.js"></script>
        <script type="text/javascript">
            var demoApp = angular.module("demoApp", ["jqwidgets"]);
    
            demoApp.controller("demoController", function ($scope) {
                // Grid data.
                var data = new Array();
                var firstNames = ["Nancy", "Andrew", "Janet", "Margaret", "Steven", "Michael", "Robert", "Laura", "Anne"];
                var lastNames = ["Davolio", "Fuller", "Leverling", "Peacock", "Buchanan", "Suyama", "King", "Callahan", "Dodsworth"];
                var titles = ["Sales Representative", "Vice President, Sales", "Sales Representative", "Sales Representative", "Sales Manager", "Sales Representative", "Sales Representative", "Inside Sales Coordinator", "Sales Representative"];
                var city = ["Seattle", "Tacoma", "Kirkland", "Redmond", "London", "London", "London", "Seattle", "London"];
                var country = ["USA", "USA", "USA", "USA", "UK", "UK", "UK", "USA", "UK"];
    
                for (var i = 0; i < 4; i++) {
                    var row = {};
                    row["firstname"] = firstNames[i];
                    row["lastname"] = lastNames[i];
                    row["title"] = titles[i];
                    row["city"] = city[i];
                    row["country"] = country[i];
                    data.push(row);
                }
    
                $scope.settings =
                {
                    altrows: true,
                    width: 800,
                    height: 200,
                    ready: function()
                    {
                        $scope.settings.apply('selectrow', 1);
                    },
                    sortable: true,
                    filterable: true,
                    showfilterrow: true,
                    source: new $.jqx.dataAdapter({
                        localdata: data,
                        datafields: 
                        [
                            {name: "firstname", type: "string" },
                            {name: "lastname", type: "string"},
                            {name: "title", type: "string"},
                            {name: "city", type: "string"},
                            {name: "country", type: "string"}
                        ]
                    }),
                    columns: [
                        { text: 'First Name', datafield: 'firstname', width: 150 },
                        { text: 'Last Name', datafield: 'lastname', width: 150 },
                        { text: 'Title', datafield: 'title', width: 150 },
                        { text: 'City', datafield: 'city', width: 150 },
                        { text: 'Country', datafield: 'country' }
                    ]
                }
                $scope.refresh = function () {
                    data = new Array();
                    for (var i = 0; i < 10; i++) {
                        var row = {};
                        row["firstname"] = firstNames[Math.floor(Math.random() * firstNames.length)];
                        row["lastname"] = lastNames[Math.floor(Math.random() * lastNames.length)];
                        row["title"] = titles[Math.floor(Math.random() * titles.length)];
                        row["city"] = city[Math.floor(Math.random() * city.length)];
                        row["country"] = country[Math.floor(Math.random() * country.length)];
                        data.push(row);
                    }
    
                    $scope.settings.source = new $.jqx.dataAdapter({
                        localdata: data,
                        datafields:
                        [
                            { name: "firstname", type: "string" },
                            { name: "lastname", type: "string" },
                            { name: "title", type: "string" },
                            { name: "city", type: "string" },
                            { name: "country", type: "string" }
                        ]
                    });
                }
    
                $scope.showGrid = true;
                $scope.toggleGrid = function () {
                    $scope.showGrid = !$scope.showGrid;
                }
    
            });
        </script>
    </head>
    <body>
        <div ng-controller="demoController">
            <jqx-button jqx-on-click="refresh()">Refresh Source</jqx-button>
            <jqx-button jqx-on-click="toggleGrid()">{{showGrid ? 'Hide Grid' : 'Show Grid'}}</jqx-button>
            <br/>
            <br/>
            <div ng-show="showGrid">
                <jqx-grid jqx-settings="settings"></jqx-grid>
            </div>
        </div>
    </body>
    </html>
    

    Best regards,
    – badera


    Dimitar
    Participant

    Hello badera,

    When the grid is hidden, its CSS property display is set to none. Widget methods should not be called for widgets that are hidden this way (as opposed to visibility: hidden;) to avoid unexpected behaviour. This is a general rule and is not restricted to the AngularJS environment.

    Best Regards,
    Dimitar

    jQWidgets team
    http://www.jqwidgets.com/


    badera
    Participant

    Thank you, Dimitar, for the explanation – and, indeed, hiding with visibility: hidden does not give any problem.
    Just because of interest and to see a little bit more in the background: Why does it give problems with display:none (and why not with visibility: hidden)? I think that in both cases the whole DOM tree is available, each element of the grid is built up… so what is the difference in point of view of the grid?


    Dimitar
    Participant

    Hi badera,

    The main issue with this is that width and height cannot be reliably measured when an element’s ancestor is hidden with display: none;. For more information, please refer to these pages: https://dev.jquery.com/ticket/125 and http://stackoverflow.com/questions/9935023/css-no-div-width-when-display-set-to-none.

    Best Regards,
    Dimitar

    jQWidgets team
    http://www.jqwidgets.com/

Viewing 4 posts - 1 through 4 (of 4 total)

You must be logged in to reply to this topic.