Sending data between controllers in AngularJS

As a newcomer to Angular, I am facing challenges in understanding how to utilize a Service to transfer data from one controller to another.

My experience with Angular so far has involved successfully calling controllers and passing data to them from within HTML. This has been particularly useful in setting up a Map Controller, where I extract results from PHP and send the data to my controller to create map markers.

However, I am struggling with passing data from one controller that generates a nested object through an ElasticSearch call to my Map Controller.

Initially, I attempted to loop through the results using ng-repeat. While I could display the results, my MapController couldn't access them in the HTML, I suspected this was due to the constraints of my IndexController.

Although I managed to output the data, I couldn't read it in MapController.

<div ng-controller="IndexController">
    <div ng-repeat="r in listingsArea.results">
        <div class="component home-listings"
            data-id="{{r.id}}"
            data-url="{{r.url}}"
            data-lat="{{r.lat}}"
            data-lng="{{r.lon}}"
            data-address="{{r.address}}"
            data-price="{{r.price}}"
        ></div>
    </div>
</div>

After researching, I found that the recommended way to pass data between controllers is through a service. However, despite following documentation, I seem to be missing something as it is not functioning as intended.

This is what I have implemented so far:

ResultsService.js

App.factory("resultsService", function() {

var loadListingsArea = {};

return {
    getLocations: function() {
        return loadListingsArea
    },

    setLocations: function(loc) {
        loadListingsArea = loc;

IndexController.js

App.controller('IndexController', function($scope, resultsService) {

$scope.listingsArea = [];

$scope.loadListingsArea = function() {
    $http.get($window.location + '/listingsarea')
        .success(function(data) {
            $scope.listingsArea = data;
        }
    );
}

$scope.$watch(function() {
    return $scope.loadListingsArea;
}, function() {
    resultsService.setLocations($scope.loadListingsArea);
});
});

MapController.js (currently just attempting to display the object)

App.controller('MapController', function($scope, resultsService) {

$scope.locations = resultsService.getLocations();

alert($scope.locations);

This is a snippet of the object when dumped from indexcontroller.js

{"count":4,
"results":[
      {"id":"1153292",
       "url":"/this-is-my-slug/1153292",
       "lat":"-37.822034",
       "lon":"144.969553",
       "address":"1302/430 Place Road",
       "price":"$2,350,000",
       "hero":"some-image-here.jpg"}
]};

Answer №1

Utilize the $http service which returns a promise directly without the need for $q.defer manipulation.

App.factory("resultsService", function() {

  var self = this;
  self.listingsPromise = undefined;

  return {
      loadLocations: function(url) {
           self.listingPromise = $http.get(url);
           return self.listingPromise;
      },
      getLocations: function() {
        return self.listingPromise;
      }
  );
}

The controller initiating the data retrieval process can use the following code snippet:

resultsService.loadLocations() // returns a promise
  .then(function(response){
    $scope.listingsArea = response.data;
  }) .catch ( function (error) {
    throw error;
  });

Meanwhile, the controller simply needing to access the data can use this code:

resultsService.getLocations()
  .then(function(response){
    $scope.listingsArea = response.data;
  }) .catch ( function(error) {
    throw error;
  });

It is important for both controllers to handle error scenarios.

Furthermore, it is crucial to note that .then handles data differently compared to .success.

The AngularJS team has deprecated the use of .success in favor of .then. It is recommended to make the switch as per the latest AngularJS $http API Docs.

Answer №2

Refactor your service by moving the $http.get request into a function. Replace the $http's promise with $q.deferred for better control.

App.factory("resultsService", function() {

  var self = this;
  self.deferred = $q.defer();
  self.listingsArea = {};

  return {
      loadLocations: function() {
          $http.get($window.location + '/listingsarea')
              .then(function(data){
                 self.listingsArea = data;
                 self.deferred.resolve(self.listingsArea);
              },
              function(e){
                self.deferred.reject(e);
              });
          return self.deferred.promise;
      },
      getLocations: function() {
        return self.deferred.promise;
      }
  );
}

The controller initiating the request can use the following:

resultsService.loadLocations() // returns a promise
  .then(function(data){
    $scope.listingsArea = data;
  });

For controllers needing the data, use the following approach:

resultsService.getLocations()
  .then(function(data){
    $scope.listingsArea = data;
  });

This may require some adjustments, but it points you in the right direction.

Keep in mind, sharing the object this way allows editing from both controllers. To prevent conflicts, pass around an angular.copy of the data object instead.

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

What exactly does a 'hoisted manifest' mean when it comes to using Yarn?

Encountering an issue while attempting to install a package using yarn, I am receiving the error message: expected hoisted manifest for \"myPackage#@material-ui/core#react-dom\" However, the concept of a 'hoisted manifest' is not entir ...

Implementing event listeners with Angular UI-Router

Currently, I am working with Angular 1.4.5 and Angular Ui Router. I am facing an issue where I am trying to utilize addEventListener to execute a function when a text field is blurred. The challenge I am encountering is that during the load state, the elem ...

What is the best way to insert a new row into a table upon clicking a button with Javascript?

Hi everyone, I'm facing an issue with my code. Whenever I click on "Add Product", I want a new row with the same fields to be added. However, it's not working as expected when I run the code. Below is the HTML: <table class="table" id="conci ...

Sequelize querying using the `WHERE NOT EXISTS()` condition

I am currently working with a many-to-many relationship setup in my database: var Genres = db.define('Movie', { name: { type: Sequelize.STRING(100), allowNull: false }, description: { type:Sequelize.STRING(), ...

Retrieve information from Django and pass it to the Vue template

I'm attempting to transfer information from Django into Vue template variables. views.py def index(request): myvar = 1 return render(request, 'index.html',{'myvar':myvar}) within index.html <span> {{ myvar }} </span& ...

Is it possible to achieve a smooth transition to the right using CSS

I'm attempting to create a sliding box effect from left to right using only transitions, similar to this: #box { width: 150px; height: 150px; background: red; position:absolute; transition: all 2s ease-out; right:auto; } .active{ bac ...

Can you clarify the dissimilarity between `knex().select("id").from("users")` and `knex("users").select("id")` in Knex?

I have successfully connected knex with mysql and am working on a login form linked to a mysql database. Currently, I am performing a login check and I'm curious if there is any distinction between the following two queries: knex().select("id").from( ...

What are some effective ways to test React Router using Jest?

Just starting out with Jest testing and looking to test the code below. import React from "react"; import "./ButtonLogin.css"; import { Link } from 'react-router-dom'; function ButtonLogin() { return ( <Link to ...

How can JavaScript be used to delete cache and cookies?

Looking for a solution to clear cache and cookies via JavaScript? I'm currently using Selenium for testing in Microsoft Edge, but the tests are running in the same session as the previous run. I need each test to run in a clean session every time. Unf ...

404 error occurs when AngularJS removes hash symbol from URLs

I successfully eliminated the hash from my Angular JS website using the following code snippet: $locationProvider.html5Mode(true); Now, the previously displayed URL has been replaced with . The issue I'm facing is that when I do a hard refresh (Ct ...

Customizing the font color and size of the MUI DatePicker default textfield is not supported

I'm encountering an issue with the MUI DatePicker as I am unable to customize the font color and font size of the date. Below is my code: const DateSettings = () => { const [value, setValue] = React.useState<Date | null>(); const handleC ...

I want to display a background color using this ng-template

enter image description hereMy code includes an ng-template that uses ngFor to generate internal HTML tags without the ability to add CSS properties. <ng-template *ngFor="let c of colors" contextMenuItem let-item (execute)="change_task_color($event.ite ...

Utilize Bootstrap multiselect for extracting values from optgroups and options

Having a select element with optgroups and bonded values, the structure is as follows: <select id="example-dataprovider-optgroups" multiple="multiple"> <optgroup label="Lime No. 2" value="b3a2eff6-5351-4b0f-986 ...

Modify the background color of a div by selecting a hex code from a dropdown menu

Is there a way to utilize jQuery in order to alter the background of a <div> by choosing the HEX code from a separate dropdown menu? HTML <select id="target"> <option value="#c2c2c2">Grey</option> <option value="blue">Bl ...

Having trouble with Bootstrap 5 Carousel not sliding to the next image? Learn how to fix this issue by upgrading from Bootstrap 4 to Bootstrap 5

Having downloaded both the compiled css and js and the source files of the bootstrap 5 library, I've experimented with both. While the css seems to load fine, I'm struggling to get this example to function. It's from a bootstrap 4 related po ...

Storing values from a content script into textboxes using a button press: a simple guide

I am new to creating chrome extensions and currently utilizing a content script to fetch values. However, I am facing difficulty in loading these values into the popup.html. Here is the code snippet: popup.html <head> <script src ...

In Angular, attempting to access and review a file prior to sending it to a server for processing

My ng-drop area allows users to upload STL formatted files to the server. I am attempting to open and generate thumbnails using the three.js library before sending these files to the server. First, I create a 'local' copy by having FileReader re ...

Guide to securely authenticate on Google Drive API asynchronously with the help of AngularJS and HTML

Is it possible for someone to help me figure out how to authenticate asynchronously with the Google Drive API using AngularJS and HTML? I seem to be stuck on the gapi.auth.authorize call because the callback function is not being called. Below is a snippet ...

A guide to retrieving data in React with useSWR whenever the state changes

In a specific scenario, I need to be able to choose users from a dropdown menu. Once a user is selected, the app should display that user's data. Upon loading the page, the app fetches the data for the first user in the array allUsers?.[0]: const [us ...

Using ng-bind-html does not offer protection against cross-site scripting vulnerabilities

I utilized ng-bind-html to safeguard against cross site scripting vulnerabilities. I came across information about sanitization and engaged in a discussion at one forum as well as another informative discussion. However, I encountered an issue where it di ...