The gridOptions.$gridScope.columns in ng-grid is modified two times when hiding or showing columns

Question:

Why does the $scope.$watch function get called twice when I manually hide/show a column but only once when I reorder/sort columns in ng-grid?

When I specifically target a single column with the watch function, it is only called once. I suspect that on hide/show actions, the entire ng-grid is changed, while on reorder/sort, only specific columns are affected.

Is there a way to determine which events trigger the function call in each situation?

Another Question:

How can I prevent the second or first invocation of the function?


I attempted to debug certain sections of AngularJS code:

if ((watchers = current.$$watchers)) {
    // process our watches
    length = watchers.length;
...
watch.fn(value, ((last === initWatchVal) ? value : last), current);
...
// in the case user pass string, we need to compile it, do we really need this ?
if (!isFunction(listener)) {
    var listenFn = compileToFn(listener || noop, 'listener');
    watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};
}

I noticed that watchers[4] and watchers[5] have identical expressions (gridOptions.$gridScope.columns), but watchers[5] has my function as its action while watchers[4] calls listenFn(scope).

My attempt to use $gridScope.renderedColumns resulted in the same issue.

Answer №1

After some experimentation, I have come up with a solution that avoids altering the ng-grid and AngularJS code:

var counter = 0;
$scope.$watch('gridOptions.$gridScope.columns', updateFunction, true);
function updateFunction(newValues, oldValues){
    if ( oldValues !== newValues && oldValues.length === newValues.length ) {
        if ( areColumnsEqual(oldValues, newValues) || isReordered(oldValues, newValues) ) {
            console.log('\n\n=====  ' + (counter++) + ' =====');
        }
    }
}

function isReordered(oldValues, newValues) {
    for ( var i = 0 ; i < oldValues.length ; i++ ) {
        if ( oldValues[i].originalIndex !== newValues[i].originalIndex ) {
            return true;
        }
    }
    return false;
}

function areColumnsEqual(oldValues, newValues) {
    for ( var i = 0 ; i < oldValues.length ; i++ ) {
        if ( oldValues[i].width !== newValues[i].width ) {
            return false;
        }
    }
    return true;
}

Now the console.log function is triggered only once for every resize, hide, show, reorder, or sort operation.


If you want to respond specifically to actions like reordering, showing, or hiding columns:

var counter = 0;
$scope.$watch('gridOptions.$gridScope.columns', columnChangeFunction, true);

function columnChangeFunction(newValues, oldValues){
    if ( oldValues !== newValues && oldValues.length === newValues.length ) {
        if ( isHideOrShowAction(oldValues, newValues) || isReordered(oldValues, newValues) ) {
            console.log('\n\n=====  ' + (counter++) + ' =====');
        }
    }
}

function isReordered(oldValues, newValues) {
    for ( var i = 0 ; i < oldValues.length ; i++ ) {
        if ( oldValues[i].originalIndex !== newValues[i].originalIndex ) {
            return true;
        }
    }
    return false;
}

function isHideOrShowAction(oldValues, newValues) {
    for ( var i = 0 ; i < oldValues.length ; i++ ) {
        if ( oldValues[i].visible !== newValues[i].visible ) {
            return true;
        }
    }
    return false;
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide on merging an array in the state of a React Component

I've been working on developing a timesheet app. In the index.js file, I have set up the rendering of a table where the rows are populated from a children array that reads the state to ensure it stays updated. The function AddRow() is functioning prop ...

How to retrieve the third party child component within a Vue parent component

Within my example-component, I have integrated a third-party media upload child component called media-uploader: <example-component> <form :action= "something"> // Other input types <media-upload :ref="'cover_up ...

Javascript: A Fun Game of Questions and Answers

When using JavaScript exclusively, I have an array consisting of four questions, four correct answers, and four incorrect answers. The use of arrays is essential to maintain order in the data. As each question is displayed, a random number is generated by ...

Encountering a CORS error in my Next.js 13.4 application while attempting to retrieve JSON data

Here is the location of the actual fetch request in our search/page. import { useSearchParams } from "next/navigation"; import Footer from "../components/Footers"; import Header from "../components/header"; import { format } ...

Press the Enter key to submit

Encountering issues while trying to enter an event. Despite reviewing several posts on this matter, a solution has not been found yet. The project needs to function properly in Chrome, FF & IE (8,9,10,11), but it is currently not working on any browser. T ...

Inserting data into a JavaScript database

When attempting to add a new row to a datatable and submit it to a JSP for database insertion, an error is encountered. The error message reads: "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the r ...

What is the best way to display a segment of an SVG on a Canvas element?

Main Issue: The main objective here is to display a specific part of an SVG image on a fixed size Canvas element within a web page. Approach I Tried: After considering various options, such as using CanVG, I thought about utilizing the viewBox attribute ...

Creating an interactive map on an image using HTML and drawing circles

I've been experimenting with drawing circles on images using the map property in HTML. I have an image set up, and when clicking on the image in JavaScript, I'm adding the area coordinates for the map property. However, I keep encountering a null ...

Different ways to utilize ng-repeat with option tags

Hello, I am currently utilizing a dropdown feature that fetches options from a database. To do this, I have created an array as shown below: const myArray = new Array(); myArray = [{className:5,avg:40},{className:6,avg:50},{className:7,avg:40}}]; Within ...

Leveraging Ajax to fetch JQuery

Currently, I am utilizing Ajax to trigger a PHP file for processing upon form submission. The JQuery form validation mechanism evaluates the variables' values to determine whether to proceed with submitting the form or to return false while displaying ...

Discover the ways in which an AngularJS function is able to generate HTML code containing an AngularJS

There is an issue here helper.getDataForTriggeredUploadOfMFFile = function (isTriggeredUploadMF) { if (!isTriggeredUploadMF) { return 'None'; } else { return '<spa ng-click=\"previewDataOnSmartAnalytics()>Preview Data</span&g ...

What could be causing my code to generate an error?

I'm encountering an error in module.js:339 where it throws an 'err' and I'm struggling to identify the exact cause or line of code that needs fixing. Any guidance on where to look would be greatly appreciated, as I seem to be searching ...

Pass a notification to a separate function

Issue Looking for a way to send an 'event' to another function using jQuery. The goal is to prevent the removal of a table row before executing certain treatments, and then remove the row. I want to insert a modal window in between these actions ...

Avoid altering the Vuex store state directly without using mutation handlers in VueJS

I am currently working on developing a listenAuth function that monitors the "onAuthStateChanged" event in firebase to inform the vuex store whenever a user logs in or out. From what I can gather, I am only updating state.authData using the mutation handle ...

Reversing the order of input-group-addon and input in bootstrap on mobile devices

I attempted to adjust the layout of a bootstrap input-group-addon on mobile devices by using two input elements and manipulating their display and visibility properties. From a design standpoint, I achieved the desired result as the input is now positione ...

"Seeking clarification on submitting forms using JQuery - a straightforward query

My goal is to trigger a form submission when the page reloads. Here's what I have so far: $('form').submit(function() { $(window).unbind("beforeunload"); }); $(window).bind("beforeunload", function() { $('#disconnectform&apo ...

Ways to empty an angularJS array

let itemList = ['X', 'Y', 'Z']; Even though the array is cleared, the user interface does not reflect the change. itemList = []; This method solves the issue. But why? itemList.length = 0; ...

Setting the initial scroll position in a ReactNative ListView after the data has been loaded

I need a solution for jumping to specific dates in an events section, with the initial scroll position set to the first future date. To achieve this, I have attempted to store the y positions of each date in the state. renderSectionHeader= (sectionData, ...

I am interested in combining identical values within a table

I have identical values in the <td>{{key}}</td> element, and I would like to avoid displaying them repeatedly. Instead, I want to merge them into a single entry. Enter image description here <tbody ng-repeat="(key, val) in myctrl.dep"> ...

Showing headings in the table vertically

I have a header1 and header2 with corresponding data1 and data2 that I want to display differently. h h e e a a d d e e r r 1 2 data1 data2 To enhance the presentation, I wish to add borders around the head ...