AngularJS: Implementing bidirectional data binding between two separate controllers using a common service

I'm currently working on establishing a two-way data binding connection between two separate controllers and a shared service in AngularJS:

app.factory("sharedScope", function($rootScope) {
    var scope = $rootScope.$new(true);
    scope.data = "initial text from factory";
    return scope;
});

app.controller("first", function($scope, sharedScope) {
    $scope.data1 = sharedScope.data;
});

app.controller("second", function($scope, sharedScope) {
    $scope.data2 = sharedScope.data;
});

Fiddle: http://jsfiddle.net/akashivskyy/MLuJA/

Upon launching the application, data1 and data2 are successfully set to the initial text from factory, but any subsequent changes made to either of them do not reflect across all three scopes.

How can I establish this binding?

P.S. If there's a more efficient approach than returning a scope while still retaining access to event and observation functionalities (without essentially redefining them), please advise. :)

Answer №1

Resolved the issue. If you are using primitives in your fiddle, be aware that references may be lost.

Take a look at this:

Updated fiddle

app.factory("sharedScope", function($rootScope) {
    var scope = $rootScope.$new(true);
    scope.data = {text: "init text from factory"};
    return scope;
});

app.controller("first", function($scope, sharedScope) {
    $scope.data1 = sharedScope.data;
});

app.controller("second", function($scope, sharedScope) {
    $scope.data2 = sharedScope.data;
});

Answer №2

Here's a creative twist: No need to inject $scope or $rootScope in this scenario. This code snippet functions perfectly when using Controller As. Take a look at the Fiddle

var app = angular.module("app", []);

app.factory("sharedScope", function() {
    var _this = this;
    _this.data = {text: "init text from factory"};
    return _this;
});

app.controller("first", function(sharedScope) {
    var _this = this;
    _this.data1 = sharedScope.data;
});

app.controller("second", function(sharedScope) {
    var _this = this;
    _this.data2 = sharedScope.data;
});

If you want even more excitement, consider treating controllers, services, and factories as classes. More Fiddles

var app = angular.module("app", []);

var SharedScope = function(){
    var _this = this;
    _this.data = {text: "init text from factory"};
    return _this;
};

app.factory("sharedScope", SharedScope);

var First = function(sharedScope){
    var _this = this;
    _this.data1 = sharedScope.data;
};

var Second = function(sharedScope){
    var _this = this;
    _this.data2 = sharedScope.data;
};

First.$inject = ['sharedScope'];
Second.$inject = ['sharedScope'];

app.controller("first", First);              
app.controller("second", Second);

I've been experimenting with the implementation of Josh Carroll's Guidelines to Avoid "Scope Soup"

Answer №3

When working with JavaScript, objects are passed by reference, meaning that all scopes will refer to the same object. To make use of this behavior, consider implementing the following setup:

app.factory("sharedData", function() {
    return {data: "initial text from factory"};
});

app.controller("first", function($scope, sharedData) {
    $scope.sharedData = sharedData;
});

app.controller("second", function($scope, sharedData) {
    $scope.sharedData = sharedData;
});

In your view, access the shared data like so:

<p>{{sharedData.data}}</p>

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

Send parameters to the $http service from a directive

I utilize this specific service model to retrieve comments from the database: .service('getComArt', function($http) { delete $http.defaults.headers.common['X-Requested-With']; this.getData = function(callbackFunc) { $ht ...

Is it not feasible to pass a local variable with the same name as a global variable in JavaScript?

const foo = "foobar"; function bar(){ const foo = foo || ""; return foo; } bar();` When running this code, it returns an empty string. Why is JavaScript unable to reassign a local variable with the same name as a global variable? Most other progra ...

What is the preferred method for accessing nested object properties in React props?

Building upon a previous inquiry - Javascript - How do I access properties of objects nested within other Objects It appears that standard dot notation doesn't suffice for accessing nested object properties within React state/props. In the case of t ...

What should be placed in the form action field if the router.post() method includes a parameter such as :id?

I'm struggling with how to properly submit data to my update form and what needs to be entered in the action field, especially considering the router.post includes an :id parameter. Below is the relevant code snippet: router.post('/gymupdate/:id& ...

Leveraging ng-repeat with a nested array in AngularJS

In my program, I have a collection of teams stored in an array called allSquads. Each team object in this array has a property called squad that contains a list of players. I need to loop through the squad array for every team in the allSquads array. When ...

Dynamically loading iframes with JQuery

I have implemented a jQuery script to load another URL after a successful AJAX request. $(document).ready(function() { var $loaded = $("#siteloader").data('loaded'); if($loaded == false){ $("#siteloader").load(function (){ ...

What is the purpose of using Array.prototype.slice.call(nodeList) for handling DOM elements?

Many JavaScript libraries like jQuery and Zepto frequently use Array.prototype.slice.call on querySelectorAll(), getElementsByTag, or ClassName results. Despite browsing numerous questions and answers on StackOverflow about this topic, I understand that it ...

What is the best way to input sorted data from a variable into a textarea field?

HTML: <button id="myButton">Click Here</button> <br /> <textarea id="imgLinks" rows="10" cols="30"></textarea> JS: $(document).ready(function() { $("#myButton").click(function() { var finalLink = '["img/1.j ...

Ways to incorporate various styles on a mobile screen for a javascript-generated function

In my current project, I have implemented a JavaScript function that renders HTML within a module. function generateHTML(bankName) { let content = `<div class="bankName" style=""><strong style="font-size: 28px;font-wei ...

What is the best way to enforce a required selection from one of the toggle buttons in a React form?

Is there a way to require the user to click one of the toggle buttons in a react form? I need to display an error message if the user submits the form without selecting a button. I tried using the "required" attribute in the form but it didn't work. H ...

What is the best approach to determine the numerical equivalents of options in a dropdown menu using PHP and JS

Hey guys, I'm really stuck on this problem and I can't seem to find a helpful tutorial anywhere. I've got a form with two drop-down menus, each with a "value" attribute. What I want is for users to be able to select an item from both drop-do ...

Is the $scope object shared among all controllers in AngularJS when nested controllers are used?

Is it possible to use nested controllers in AngularJS? When using nested controllers, is the $scope object shared across all controllers? The issue at hand is:- While I can access the $scope values of the first controller across all controllers, I am una ...

JavaScript closing of a window

I've been dealing with this issue for the past few hours. Currently, I am utilizing the iframe version of LightFace modal windows: http://davidwalsh.name/facebook-lightbox The problem I'm encountering is the inability to close the modal from w ...

Exploring the functionality of Array.prototype.includes() in Angular 7 with PhantomJS testing

While testing components in my Angular application, I noticed that unit tests utilizing Array.prototype.includes() are successful in Chrome but fail when executed with PhantomJS. I found some suggestions in the responses to this question related to a simi ...

Create a pop-up window within a single controller using Angular.js

I followed a tutorial to create this code. I am interested in learning how to utilize just one controller for generating the dialog box. Currently, I am using two controllers for this project. Any guidance or tips would be greatly appreciated. View my cod ...

Exploring the way Google indexes Angular-based websites with HTML5 URLs

Currently working on a web application that has the following URL structure: / serves as the landing page without Angular /choose utilizes Angular for search functionality /fund/<code> also Angular based, provides spec ...

React - 'classProperties' is not currently activated in this setting

Recently, I incorporated Truncate-react into my project. Subsequently, React prompted me to install @babel/plugin-proposal-class-properties, which I promptly added to the package.json file as follows: "babel": { "presets": ...

Create a Vue JS component that enables the rendering of checkbox inputs and sends the selected values back to the

I am working on a Vue JS project where I am creating a custom component to display multiple checkboxes on the page. The challenge I am facing is sending back the value to the component in order to attach a v-model to it. Currently, all my checkboxes allow ...

Adding up whole numbers from a string - JavaScript

JavaScript is still very new to me and I'm facing a challenge: I have an array containing three phone numbers, and I need to calculate the sum of the digits in each phone number string. I want to find and return the phone number with the highest ...

Applying a CSS transition to transform properties excluding rotation effects

I'm looking to apply a transitional animation to an element's transform property without affecting the rotation. Here is the code snippet: <html> <head> <link rel="stylesheet" href="style.css"> <script src="script.js ...