The issue of Angular's ng-repeat view not refreshing after a search query remains unresolved

Having some trouble with updating a results array in AngularJS using a service call. After submitting a form and calling the service, I set up my callbacks with .then() on the promise object. However, the view only updates when I start deleting characters from the input field. At that point, it displays the correct results.

Here's how my view looks:

<div id="main" ng-controller="SearchController as searchCtrl">
        <div class="header" >
            <h1>Search and Add Tracks</h1>
        </div>
        <form class="pure-form pure-g" novalidate ng-submit="searchCtrl.search()">
            <div class="pure-u-1">
                <input class="pure-input-1" type="search" placeholder="Search for tracks" ng-model="searchCtrl.query">
            </div> 
        </form>

        <div class="pure-u-1" >
            {{searchCtrl.results.length}}
            <div ng-repeat="track in searchCtrl.results" ng-include src="'templates/single-track-view.html'" >
            </div>
        </div>
    </div>

And here is my controller code:

app.controller('SearchController',function(){
    var searchCtrl = this;
    searchCtrl.results = [];
    searchCtrl.query = '';

    this.search = function(query){
        console.log(searchCtrl.query);
        var processTracks = function(results){
            console.log(results);
            searchCtrl.results = results[0].tracks;
            searchCtrl.results.push(results[1].tracks);
            searchCtrl.query = '';
            return results;
        }
        
        mopidy.library.search({"any": searchCtrl.query}).then(processTracks,console.error.bind(console));
    }

});

Upon inspecting the scope with the AngularJS inspector, I can see that searchCtrl.results is being updated correctly with the results. However, the view does not update until I start deleting characters.

EDIT: It turns out that the result returned from the promise is actually an array of responses. The API I'm calling from Mopidy (a music player) sends different responses from various music providers.

Answer №1

Initiating $scope.$apply can be risky, however the issue lies within the digest loop.

A better approach would involve integrating the call into Angular by using $q.when:

app.controller('SearchController',function($q){ // $q is used for promises
    var searchCtrl = this;
    searchCtrl.results = [];
    searchCtrl.query = '';

    this.search = function(query){
        console.log(searchCtrl.query);
        var processTracks = function(results){
            console.log(results);
            searchCtrl.results = results[0].tracks;
            searchCtrl.results.push(results[1].tracks);
            searchCtrl.query = '';
            return results;
        }
        //$q.when integrates a third party promise into Angular
        $q.when(mopidy.library.search({"any": searchCtrl.query}))
        .then(processTracks,console.error.bind(console));
    }

});

But why does it work? What's $q?

Upon closer examination of the code, we see the use of .then.

This .then is how a promise - an abstraction over concurrency - indicates that the value of the API call is now available.

Promise libraries follow a specification called "Promises/A+" which dictates how they interact with each other. Therefore, Angular's promise library - $q - can seamlessly handle the mopidy.library promise.

Angular's $q promises are directly linked to the digest loop, so converting a third-party promise into an Angular one ensures that it runs in sync with the digest loop, eliminating the need for a manual second digest.

Answer №2

It doesn't make sense unless the property you are tracking is an array.

      searchCtrl.results = results[0].tracks;
      searchCtrl.results.push(results[1].tracks);

If it is an array, you will break the link between ng-repeat and the observed variable by redefining it. Also, if Mopidy is an external library, you will need to apply your changes after updating the results variable.

Answer №3

As highlighted by others, the key solution in this scenario is to execute $scope.$apply();

The rationale behind it: When an XHR request is made, it operates independently from Angular's usual digest cycle, which is responsible for updating all the listeners related to two-way data binding. By invoking $apply, a digest is triggered to ensure that all relevant models are updated.

Refer to Angular documentation on $apply

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

Press on a rectangle inside an HTML5 SVG program

I'm currently developing a web application that utilizes the svg and Raphael library: workflowEditor.show(); var myList = document.getElementsByTagName("rect"); for (var a = 0; a < myList.length; a++) { myList[a].addEventListener("OnClick", f ...

Looking for assistance with JQuery and JavaScript?

I oversee a team of employees, each with a 7-day work schedule. To streamline the process, I have developed a PHP form that I would like to use to collect data for verification in JavaScript before submitting it to an SQL database using AJAX. My main cha ...

Error message: An error occurred while executing the AJAX PHP code due to a TypeError, specifically stating that the property 'status' cannot be

For some reason, I keep receiving an undefined return for my response. The event handler in index.php triggers the following code: $.post("getData.php", onNewPost()); function onNewPost (response){ if (response.status == "OK") { console.log(resp ...

Navigating between two table components in React JS

I am a beginner in the world of React and I am struggling with switching between these two tables. Despite consulting the documentation for inline conditional statements, I still couldn't figure it out. My goal is to have the tables switch after click ...

Using Mongoose to Perform Lookup with an Array as a Foreign Key

In my database, I have a collection called questions which contains fields like _id, name, and more. Additionally, there is another collection named tests with fields such as _id, name, and an array of questions. My goal is to retrieve all the questions a ...

Error 400 when uploading files in Angular2 using multipart/form-data

When attempting to upload a file along with some meta information using multipart/form-data, the format should look like this: Header ----boundary Meta ----boundary File ----boundary Despite following this format, I consistently receive a 400 Error from ...

"Problems with the YouTube API functions: playVideo, pauseVideo, and stopVideo not

Currently, I am working on integrating the YouTube API to control a group of players within a slideshow. My goal is to pause and play videos based on which slide the slideshow is on. I have tried storing the players in an array using the frame's id. W ...

Loop through each object and add them to an array in a file using NodeJS

Currently, I have a scenario where I am executing a POST request inside a for loop function and the response needs to be stored as an object in an array file. Below is the code snippet that I am utilizing: var arrayFile = fs.createWriteStream("arrayFile.j ...

Determining percentage using input fields within AngularJS

I am currently working with AngularJS and have a form with two input fields: total marks and marks obtained. I also have a third field for percentage, which I want to calculate automatically based on the entered values. Below is the HTML code: <div cl ...

Storing data in a table created through a belongsToMany relationship in Sequelize and retrieving it. (Solution provided below)

My backend setup includes Node.js, Express.js, and Sequelize for database connections. I have established a many-to-many relationship between Tasks and Keys. I defined the connection between Tasks and Keys using Sequelize as follows: Backend // Task ...

Encountering a problem in Angular 2 when trying to pass undefined variables between components while fetching data from

My approach involves making a single API call and storing the response in a global variable within my Service. I then utilize two helper functions to share and manipulate this value between parent and child components. repairs.service.ts public myItems:a ...

Angular and Express encountering a CORS 403 issue

My Express configuration includes settings that run on a different domain: app.use(function(req, res, next) { res.setHeader("Access-Control-Allow-Origin", 'http://localhost:3000'); res.setHeader("Access-Control-Allow-Credentials","true") ...

Show pictures in AngularJS Modal with ng-repeat loop

Here is the index.html document: <!DOCTYPE html> <html ng-app="myApp" ng-app lang="en"> <head> <meta charset="utf-8"> <link href="css/bootstrap.min.css" rel="stylesheet"> <style type="text/css"> ul>li ...

Tips for creating a static background when displaying a modal popup in AngularJS

Incorporating a modal popup to modify a row within a grid view has been my recent task. Leveraging the row.getProperty() function, I successfully extracted the row values within the modal. However, an inconvenience emerged when attempting to edit a value ...

Utilizing PHP to fetch data from a separate webpage

This is a question that has sparked my curiosity. I am not facing any particular issue that requires an immediate solution nor do I possess the knowledge on how to achieve it. I have been contemplating whether it is feasible to utilize PHP for fetching co ...

Getting a list of connected users on a PeerJS server using Express is simple and straightforward. Follow these steps to

Trying to incorporate PeerJS, a webRTC library, into a game and utilizing their server for user discovery has proven challenging. The goal is to manage a list of connected users, but grappling with the PeerJS server has been difficult. The documentation s ...

The Ajax script is malfunctioning

Currently, I have a program that requires the user to input a city and country. The program then checks the database to see if the city already exists - displaying a warning message using ajax if it does, or adding the city to the database if it doesn&apos ...

Exploring the intricacies of debugging async/await in Node.js with the help of

Having trouble debugging an "await" instruction in my async function. Every time I try, a promise is returned instead of the expected value. I've noticed there's supposed to be an "Async" button where the red square is located in this picture but ...

Is there a way to adjust the image dimensions when clicked and then revert it to its original size using JavaScript?

Is there a way to make an image in an HTML file change size by 50% and then toggle back to its normal size on a second click using JavaScript? I've attempted to do it similar to the onmouseover function, but it doesn't seem to be working. Any sug ...

Creating and deleting HTML elements in a dynamic array format

My current approach involves utilizing jQuery and JavaScript for the purpose of dynamically adding and removing HTML elements. Specifically, I am focusing on the removal of particular HTML elements. The code snippet is as follows: $(document).ready(fun ...