Is the Angular ng-init causing issues with updating the model in the $scope function?

I am currently developing a test web application. The primary functionalities at the moment are user login and posting messages.

When the user clicks a button, the following code is triggered:

$scope.getData = function(){
    $http.get('/messages').
        then(function(response) {
            if(angular.toJson(response.data.messages) != angular.toJson($scope.messages)) {
                $scope.messages = response.data.messages;
                $scope.clearAllSelected();
                $scope.confirmRestOperation(response);
            }
        }, function(response) {
            $scope.messages = [];
            $scope.confirmRestOperation(response);
        });
};

The HTML template associated with my model looks like this:

<div id="messages">
<md-card ng-repeat="message in messages" class="padding-medium box-sizing" ng-init="setAuthorDataFromAuthorId(message.author)">
  <md-checkbox class="md-primary" ng-click="toggle(message.id, selected)" ng-model="exists(message.id, selected)"></md-checkbox>
  <h4><b>Author: {{authorData[message.author].name}} ({{authorData[message.author].username}})</b></h4>
  <img style="width:50px;height:50px;" ng-src="{{authorData[message.author].profile_picture}}" alt="(Picture)">
  <p>Message: {{message.message}}</p>
  <p>{{message.time | timestampToDate}}</p>
</md-card>
</div>

The objective here is to have each message contain an 'author' field which holds the author's ID. Upon initializing each card, I invoke a $scope function called setAuthorDataFromAuthorId, which takes an integer value - the ID of the message author. The function is as follows:

$scope.setAuthorDataFromAuthorId = function(id) { // line 22
    console.log($scope.authorData);               // line 23
    if(id in $scope.authorData) return;
    console.log("setAuthorFromAuthorId has been called");
    $http.get('/getUserDataFromId/'+id).then(function(response) {
        console.log(response.data);               // line 27
        console.log($scope.authorData);           // line 28
        $scope.authorData[id] = response.data;
    }, function(response) {
        console.log(response.data);
        console.log($scope.authorData);
        $scope.authorData = {};
    });
    console.log("setAuthorFromAuthorId has been completed");

};

The issue arises when multiple messages from the same author are displayed on the screen. Despite attempting to prevent redundant API calls by checking if the author's data is already present in $scope.authorData, the output displays inconsistent behavior.

After switching the initialization method from ng-init to ng-click, the functionality improved significantly. However, I am still puzzled about why the original approach failed to work seamlessly with ng-init.

Any suggestions on resolving this issue or insights into why ng-init may not be functioning as expected would be greatly appreciated.

Thank you!

Answer №1

Forget about using the ng-init directive, instead, place the initialization logic inside the controller.

Utilize chaining from the initial $http request.

Implement the following code to execute when the user clicks a button:

$scope.getDataAndInitPromise = function() {
  $scope.pendingFlags = $scope.pendingFlags || {};
  var promises = [];

  //calculate getDataPromise
  var getDataPromise = $scope.getDataPromise();

  //chain from getDataPromise
  var initListPromise = getDataPromise.then (function() {
    angular.forEach($scope.messages, function(m) { 
       var id = m.author;
       if ($scope.pendingFlags[id] == "pending") return;
       if(id in $scope.authorData) return;
       console.log("setAuthorFromAuthorId has been called");
       //set pending flag
       $scope.pendingFlags[id] = "pending";
       var p = $http.get('/getUserDataFromId/'+id
                ).then(function(response) {
                    console.log($scope.authorData);
                    $scope.authorData[id] = response.data;
               }).catch(function(error) {
                    //log error     
               }).finally ( function() {
                    console.log("setAuthorId %s done ", id);
                    //clear pending flag
                    $scope.pendingFlags[id] = "done";
               });
        //add promises to array
        promises.push(p);
    });
    //return array of promises for further chaining
    return promises;
  });
  //return for additional chaining
  return initListPromise;
}

Take note of the usage of pendingFlags to prevent redundant fetches and the relocation of the "done" console.log statement into a .finally method.

Ensure to adjust the getData function to return a promise for chaining purposes.

$scope.getDataPromise = function(){
  var  getDataPromise = 
    $http.get('/messages').
        then(function(response) {
            if(angular.toJson(response.data.messages) != angular.toJson($scope.messages)) {
                $scope.messages = response.data.messages;
                $scope.clearAllSelected();
                $scope.confirmRestOperation(response);
            }
        }, function(response) {
            $scope.messages = [];
            $scope.confirmRestOperation(response);
        });
  //return promise for chaining 
  return getDataPromise;
};

Harness the potential of promises.

Do not discard those httpPromises; make good use of them.

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

Creating a topographical map from a 3D model

<!--B"H--> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Custom Terrain Heightmap Generator</title> ...

Implementing a React app mounting functionality upon clicking an HTML button

Is there a way to mount a react application by clicking on a standard html button outside of the application itself? My index.html layout is as follows: <div id="app"></div> <button id="button-root">Live chat</butt ...

Setting a default checked radio button option in Angular

I'm looking to have a default radio button option checked, but so far my attempts with ng-model and ng-init haven't been successful. Here's my HTML: <div bindonce ng-repeat="row in results.favorites" style="padding: 0px 10px; white-spac ...

Dynamically assigning column values based on object properties

I am currently utilizing the Ionic Framework along with its grid system that is reminiscent of Bootstrap. However, I believe my query leans more towards AngularJS than specific Ionic components. Here is what I have: <ion-col *ngFor="let col of row ...

What is the best way to export two functions from a server-side module in JavaScript?

Working with Node/Express. In my project, I have an index.js server file and a separate js module called validmoves.js. Usually, to export a single function from a module, I can simply use the following syntax: module.exports = shuffleFunction; Then, i ...

Which programming language should I utilize to create a webpage that dynamically updates its content from a database?

Seeking advice on a complex task I'm facing. I'm currently managing a vast spreadsheet (266 rows with 70 columns, and growing) which serves as a database. I want to transfer this data from Excel to an intranet page. Currently, I'm using a mi ...

What are the advantages of combining a library (using Rollup or Webpack) instead of simply transpiling it with Babel?

When developing a library in JavaScript, what are the benefits of using tools like Rollup or Webpack for bundling rather than just transpiling with Babel? One potential advantage could be that by bundling, you ensure that your dependencies are packaged eff ...

Waiting for jQuery to complete iteration with $.each function

Hey there, I've been dealing with a persistent issue that I can no longer ignore. The function below sends a post request for every checked box when executed. However, I need it to wait until the $.each loop has finished processing before refreshing t ...

Experiencing difficulties with updating populated inputs that are connected to fetched data as they are not reflecting changes when modified

I am currently facing challenges with handling text fields in my web application. I need to retrieve data from the database, populate it in the appropriate fields, allow users to edit the information, and save any changes made. However, I have encountered ...

Node.js assert causes mocha to hang or timeout instead of throwing an error when using assert(false)

I am facing an issue with a mocha test that I have written: describe 'sabah', → beforeEach → @sabahStrategy = _.filter(@strats, { name: 'sabah2' })[0] .strat it 'article list should be populated&ap ...

How can we implement :focus-within styling on Material-UI Select when the input is clicked?

I am currently implementing a Select component inside a div element: <div className="custom-filter custom-filter-data"> <DateRangeIcon className="search-icon"/> <FormControl variant='standard& ...

How to troubleshoot syntax errors when using the delete function in Three.js within Eclipse

When using the Javascript Library Three.js, it is important to note that the delete keyword can be used as an object property. While this is valid under ECMAScript 5 standards, Eclipse currently only supports ECMA 3. As stated in the Mozilla reference, re ...

How can I generate spheres in threejs with varying radii while all passing through the shared point located at coordinates (0,0,200)?

Is there a way to generate spheres in threejs where the radius increases while always passing through a single point at 0,0,200? This would allow the origin of each new sphere to move along the z-axis. Appreciate any help, AriemWebgl ...

a dedicated TypeScript interface for a particular JSON schema

I am pondering, how can I generate a TypeScript interface for JSON data like this: "Cities": { "NY": ["New York", [8000, 134]], "LA": ["Los Angeles", [4000, 97]], } I'm uncertain about how to handle these nested arrays and u ...

Double-triggering iOS share sheet [Cordova/Ionic/Angular] prompts

There seems to be an issue with the share sheet in iOS firing twice when the n-click share button is pressed in my app menu. The first share sheet appears, followed by another on top of it. In the menu.html file... <ion-nav-buttons side="right"> ...

Accessing an element by its ID with the help of a looping

Looking to retrieve a string from my database and insert it into my paragraphs: <p id="q_1"></p> <p id="q_2"></p> The following code works correctly: $.get("bewertung/get/1", function (data) { document.getElementById("q_1") ...

Updating the redux state in react by passing a variable from a child component to the parent

I'm currently in the process of updating my Redux state within a component by utilizing a variable that has been passed up to the component from a child, specifically through a form submission callback. The form is responsible for submitting a user&ap ...

Ways to dynamically update the content of an HTML table without the need to reload the page

I'm currently working on an HTML table that retrieves data from a database and includes a button for deleting selected records. Here is what the table layout looks like: name phone links john 6562 link1 link2 link3 ___________ ...

value of previous checkbox selection

http://jsfiddle.net/thetylercox/gy8EQ/20/ $(':checkbox').change(function() { if (this.checked) { var lastChecked = $(this).prevAll(":checked:first"); if (this.value == lastChecked.val()) { alert("previous checke ...

Retrieving JSON data from AngularJS in Flask

I am facing an issue with my AngularJS app. It sends data using HTTP PUT to a flask server, and while the data reaches the server correctly, the flask method is unable to read it when the HTTP PUT request is made by Angular... Flask code: @app.route(&apo ...