Tips for utilizing Angular 1.x services to refresh one component from another

I have a main component that contains numerous smaller components within it. The primary goal is to have one component receive input data and display it in another component. The current implementation isn't functioning as expected, additional details on the issue will be provided below:

const app = angular.module('app', []);

app.service('dataService', function() {
  let data = {
    key1: "",
    key2: "",
    key3: {
      key4: 0,
      key5: 0
    }
  }

  this.getKey1 = function() {
    return data.key1;
  }

  this.updateKey1 = function(str) {
     data.key1 = str;
  }
}

app.component('display', {
  controller: displayController,
  template: '<p>{{ keyOne }}</p>'
});

app.component('input', {
  controller: inputController,
  template: '<input ng-model="$ctrl.key1" ng-change="sendKey1()">'
}

function displayController($scope, dataService) {
  const vm = this;
  const self = $scope;
  vm.$onInit = onInit;
  function onInit() {
    self.keyOne = dataService.getKey1();
  }
}

function inputController($scope, dataService) {
  const vm = this;
  const self = $scope;
  vm.$onInit = onInit;
  function onInit() {
    self.sendKey1 = function() {
      dataService.updateKey1(vm.key1)
  }
}

The update operation is successful, but the data doesn't get passed to the display component. Even though the data object reflects the correct information after updating, it fails to appear in the view.

Answer №1

You are making changes to a string data.key1 = str; within the

let data = {
    key1: "",
    key2: "",
    key3: {
      key4: 0,
      key5: 0
    }
  }

In Angular, only objects can be bound between components, not strings.

Check out this link https://plnkr.co/edit/wfwyyGpcMKOSHGFdg2DS?p=preview

var app = angular.module('plunker', ['ngRoute', 'ngAnimate', 'ngSanitize']);

app.service('dataService', function() {
  let data = {
    key1: "",
    key2: "",
    key3: {
      key4: 0,
      key5: 0
    }
  }

  this.getData = function() {
    return data;
  }

  this.updateKey1 = function(str) {
    data.key1 = str;
  }
});



app.component('inputc', {
  controller: inputController,
  template: '<input ng-model="$ctrl.key1" ng-change="sendKey1()">'
});

app.component('display', {
  controller: displayController,
  template: '<p>{{ data.key1 }}</p>'
});

function displayController($scope, dataService) {
  const vm = this;
  const self = $scope;
  vm.$onInit = onInit;

  function onInit() {
    self.data = dataService.getData();
  }
}

function inputController($scope, dataService) {
  const vm = this;
  const self = $scope;
  vm.$onInit = onInit;

  function onInit() {
    self.sendKey1 = function() {
      dataService.updateKey1(vm.key1)
    }
  }
}
<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link href="style.css" rel="stylesheet" />
    <script src="https://code.angularjs.org/1.6.2/angular.js"></script>
    <!-- By setting the version to snapshot (available for all modules), you can test with the latest master version -->
    <!--<script src="https://code.angularjs.org/snapshot/angular.js"></script>-->
    <script src="https://code.angularjs.org/1.6.2/angular-route.js"></script>
    <script src="https://code.angularjs.org/1.6.2/angular-animate.js"></script>
    <script src="https://code.angularjs.org/1.6.2/angular-sanitize.js"></script>    
    <script src="app.js"></script>
  </head>

  <body>
    <inputc></inputc>
    <display></display>
  </body>
  
  

</html>

Answer №2

Check out this interesting article on A Tale of Frankenstein and Binding to Service Values in Angular.js.

Here is a brief summary of the scenario:

  1. displayController runs
    self.keyOne = dataService.getKey1()
    , which sets an empty string to $scope.keyOne.
  2. The expression {{ keyOne }} in the view monitors changes in $scope.keyOne. Initially, it displays "", showing an empty string in the view.
  3. inputController updates dataService.data.keyOne with a new value, like hello world.
  4. The expression {{ keyOne }} once again checks for changes in $scope.keyOne during the digest cycle. Issue: $scope.keyOne remains an empty string! The displayController fails to retrieve the latest value from dataService.data.keyOne.

Thankfully, there is a simple solution. You just need to access the data object directly to accurately evaluate

data.keyOne</code when monitoring changes:</p>

<pre><code>app.service('dataService', function() {
  let data = {
    key1: ""
  }

  //Expose the data object
  this.getData = function() {
    return data;
  }
}

app.component('display', {
  controller: displayController,
  //Evaluate the current value of keyOne in the data object
  template: '<p>{{ data.keyOne }}</p>'
});

function displayController($scope, dataService) {
  const vm = this;
  const self = $scope;
  vm.$onInit = onInit;
  function onInit() {
    //Get a static reference to the data object.
    //The data object itself shouldn't change, but its properties will.
    self.data = dataService.getData();
  }
}

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

Issue with close request on dialog box

Whenever an icon is clicked, a dialog box containing a form should appear. The purpose of this dialog box is to either add a new tab or delete a specific tab. In my implementation, I used ReactJS, Redux, and Material-UI for building the components. Even th ...

My Contentful code is not functioning properly in NodeJS

I am encountering an issue with the code below, which is meant to display content of type "course." When I try to access http://localhost:3000/api/courses, the browser keeps loading indefinitely without any error messages in the console. Interestingly, t ...

Leveraging React Hooks and Axios for retrieving data and showcasing it in a table

I have set up a React environment, created a hook named ApiTable, and implemented a method called renderTable. My goal is to fetch data from the API endpoint located at https://jsonplaceholder.typicode.com/users, and display it in a table with the appropri ...

After a pinch gesture to zoom in on HereMaps using JavaScript, the getZoom() function unexpectedly returns a value

We are in the process of creating an Android app (targeting API 19 and above) using C# and the Xamarin framework. One of the key features is a map embedded within a WebViewClient - specifically, we are utilizing Here Maps rendered through the Here Maps JS ...

Exploring the features of Meteor subscriptions within React

I'm currently exploring the combination of React.js and Meteor.js, attempting to integrate Meteor's subscribe feature into React, based on a helpful blog post I came across. My goal is to have the front end update dynamically whenever there are c ...

The jQuery selector for input[type=text]:nth-child(2) is malfunctioning

I cannot utilize the ids or class names linked to the inputs because they are randomly generated on input. Here is how the render appears: <div class='dateSearch'> <label>Label 1</label> <input type='text' id=& ...

Explore the scope of each item in ng-repeat

My table has rows that use their respective scope variables for conditional rendering: <tr ng-repeat="row in data"> <input type="text" data-ng-show="editMode" data-ng-model="row.smth"/> The input is only shown when the row's scope vari ...

Incorrect date and time displayed

When using this code: <td><% district.created_at %></td> The resulting output is: 2022-08-06T09:14:58.000000Z However, it should look like this: 2022-08-06 09:14:58 The correct format is generated by Laravel 5.3 while the incorrect one ...

Converting a JavaScript object to JSON within Node-RED

I am attempting to convert a JavaScript object created in my Node-RED flow to JSON format, but I am struggling to figure out how to do it. The object consists of an hour and minute displayed on the screen, such as "13:02". I need to see this in JSON format ...

Finding the Vue module within a helper function or mixin: A step-by-step guide

In my development work with Nuxt.js, I am utilizing the cookie-universal-nuxt package to access cookies in both server-side and client-side. modules:[ [.....] , [.....] , [.....] , ['cookie-universal-nuxt', { alias: 'myCookie' ...

Tips on retrieving data from an http request in Angular 2 after it has been successfully made

Consider this example function: getSessionInfo() { this._http.get(someCorrectUrlHere) // It is unclear what this map function does .map(res => res.json()) // It is unclear what this subscribe function does .subscribe( data = ...

The Await function is incompatible with MongoDB collections

Struggling with retrieving the current collection from mongodb. A file contains a FetchUsers function that returns a user collection: const mongoose = require('mongoose'); const uri = "mongodb+srv://<username>:<password>@<cluster- ...

The proper way to style JQuery UI calendar dates

I came across a jquery-ui angular date picker directive that I'm using. It's working well, but the format when it displays a date from the database is not what I need - currently showing as 2014-08-10T00:00:00. I require the mm-dd-yy format inste ...

Is there a way to directly load an SVG for a leaflet divIcon without having to import it through a js file?

There is a sample Vue 2 project available at this GitHub repository I am looking to integrate an SVG into a leaflet divIcon. const cloudIcon = L.divIcon({ html: thecloud, // this.cloudSvg, // thecloud, className: 'my-custom-icon ...

Generate HMAC hash using C# within a Javascript environment

Below is a C# function that I have; private string GetEncyptionData(string encryptionKey) { string hashString = string.Format("{{timestamp:{0},client_id:{1}}}", Timestamp, ClientId); HMAC hmac = HMAC.Create(); hmac.Key = Guid.P ...

Tips for triggering useEffect just once when various dependencies are updated simultaneously

Currently, I have implemented a useEffect hook with two dependencies in the following way: useEffect(() => { ..... }, [apiData, currentMeasurements]); It's important to note that the apiData is fetched using useLazyQuery from apollo/client. Upon ...

Should the use of "onClick={}" be considered poor practice?

Recently, I discovered that the use of onclick is not recommended in HTML. Currently, I am immersing myself in a React tutorial where they utilize <button onClick={shoot}>Take the Shot!</button>. I'm curious if this practice applies to Rea ...

What is the reason behind being limited to sending only 5 requests if I fail to heed the data event?

I've come across some related questions while researching this topic, such as Why is node.js only processing six requests at a time?. However, I am still struggling to fully grasp the specifics. Below is a breakdown of my scenario: Firstly, let&apos ...

Retrieve the id of the clicked hyperlink and then send it to JQuery

<a class = "link" href="#" id = "one"> <div class="hidden_content" id = "secret_one" style = "display: none;"> <p>This information is confidential</p> </div> <a class = "link" href="#" id = "two" style = "display: non ...

Ways to trigger a function in the parent component from a nested child component using Angular 1x

A situation arises where I have a parent component named purchaseComponent and a child component called supplierComponent. The supplier component operates independently when loaded in a full view. Furthermore, I am able to successfully load the supplierCom ...