Modify the value of a service from the main controller

I have been researching extensively on how to edit a service value from a nested controller. The issue I am facing is that my child controller needs to update a specific value in a service, and this value must be reflected in the parent controller as well.

To provide a clearer understanding and facilitate assistance, I have created a demonstration on jsfiddle: http://jsfiddle.net/jtsmduxw/3/

<body ng-app="MyApp">
    <div ng-controller="parentCtrl">
        <p>{{username}}</p>
        <div ng-controller="childCtrl">
            <p>{{username}}</p>
        </div>
    </div>
</body>

-

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

app.service('authenticationSrv', function () {
    var user = 'anonymous';
    return {
        getUser: function () {
            return user;
        },
        setUser: function (value) {
            user = value;
        }
    };
});

app.controller("parentCtrl", function ($scope, authenticationSrv) {
    $scope.username = authenticationSrv.getUser();
});

app.controller("childCtrl", function ($scope, authenticationSrv) {
    authenticationSrv.setUser('my name'); // My goal is for this function to update the parent's scope as well
    $scope.username = authenticationSrv.getUser();
});

(Although I have explored and attempted solutions from Update parent scope variable, I have not been successful in implementing them with the service.)

Thank you!

Answer №1

Instead of using the variable username, consider utilizing an object literal.

Parent

app.controller("parentCtrl", function ($scope, authenticationSrv) {
    $scope.parentObject = {};
    $scope.parentObject.username = authenticationSrv.getUser();
});

Child

app.controller("childCtrl", function ($scope, authenticationSrv) {
    authenticationSrv.setUser('my name'); 
    $scope.parentObject.username = authenticationSrv.getUser();
});

Example in Action

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


app.service('authenticationSrv', function () {
    var user = 'anonymous';
    return {
        getUser: function () {
            return user;
        },
        setUser: function (value) {
            user = value;
        }
    };
});

app.controller("parentCtrl", function ($scope, authenticationSrv) {
    $scope.parentObject = {};
    $scope.parentObject.username = authenticationSrv.getUser();
});

app.controller("childCtrl", function ($scope, authenticationSrv) {
    authenticationSrv.setUser('my name'); 
    $scope.parentObject.username = authenticationSrv.getUser();
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="MyApp">
    <div ng-controller="parentCtrl">
        <p>{{parentObject.username}}</p>
        <div ng-controller="childCtrl">
            <p>{{parentObject.username}}</p>
        </div>
    </div>
</body>

Answer №2

Transform the `user` variable in the Service into an object rather than a simple string. Then, utilize `{{user.name}}` in your view.

I made some slight modifications to `authenticationSrv.setUser()` by changing it to `authenticationSrv.setUserName()`.

Take a look at my live example: https://jsfiddle.net/rbwk3rqb/

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

angular.module("MyApp")
.service('authenticationSrv', function () {
    var user = {name: 'anonymous'};
    return {
        getUser: function () {
            return user;
        },
        setUserName: function (value) {
            user.name = value;
        }
    };
});

angular.module("MyApp")
.controller("parentCtrl", function ($scope, authenticationSrv) {
    $scope.user = authenticationSrv.getUser();
});

angular.module("MyApp")
.controller("childCtrl", function ($scope, authenticationSrv) {
    authenticationSrv.setUserName('my name');
    $scope.user = authenticationSrv.getUser();
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="MyApp">
    <div ng-controller="parentCtrl">
        <p>{{user.name}}</p>
        <div ng-controller="childCtrl">
            <p>{{user.name}}</p>
        </div>
    </div>
</body>

Answer №3

When integrating the primitive value user from the service into your controller's scope with the line:

$scope.username = authenticationSrv.getUser();

the value of user gets copied into $scope.username. Even if you later update the value of user in the service, it does not change within your "parent" $scope.

To workaround this, one simple solution is to create a user object in your service - by storing a reference to this object in your scopes, any alterations made to it in other controllers will be reflected. (In JavaScript, objects are passed by reference value, meaning all controllers will manipulate the same object, not copies of values.) Regarding the implementation details, you can refer back to the same link you shared - if you faced any issues while applying it, please share the code you attempted.

Another approach is to utilize the observer pattern within this service (although it involves more effort), or use events on the scope hierarchy to inform controllers of user changes (though this practice is debatable).

Answer №4

The concept revolves around creating an object for updating, rather than just a primitive value:

$scope.account = {};
$scope.account.username = authenticationService.getUser();

Then, in the child scope, you simply assign it like this:

$scope.account.username = authenticationService.setUser('new username');

Check out this Demo for a visual representation.

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

Extending the declaration of JavaScript native methods is not possible when using TypeScript

When attempting to enhance the JS native String class by adding a new method, I encounter error TS2339. interface String { transl(): string; } String.prototype.transl = function() { // TS2339: Property 'transl' does not exist on type 'St ...

Achieving a dynamic "Picture Presentation" feature with JavaScript/jQuery

Currently, I am in the process of developing a website that will serve as a presentation. My plan is to create a slideshow effect using JavaScript. While I have implemented some functions, I must admit that it is not very organized at the moment. The main ...

Can you explain the contrast between onsubmit="submitForm();" and onsubmit="return submitForm();"?

Is it possible that the form below is causing double submissions? <form name="myForm" action="demo_form.asp" onsubmit="submitForm();" method="post"> function submitForm(){ document.myForm.submit(); } I've noticed a bug where sometimes two ...

What could be the reason that the painting application is not functioning properly on mobile devices?

I am facing an issue with my painting app where it works perfectly on desktop browsers but fails to function on mobile devices. I tried adding event listeners for mobile events, which are understood by mobile devices, but unfortunately, that did not solve ...

Running res.render in an asynchronous manner within an express application

My goal is to make this router respond asynchronously: var express = require('express'), router = express.Router(); router.get('/', function(req, res, next) { res.render('contact', { titleShown: true, title: & ...

Vue.js custom confirmation component failing to open within v-menu

I am having trouble displaying a confirmation component every time a button in the header is clicked. Currently, it only opens when clicking elements outside of the dropdown using v-menu. App.vue <template> {{isConfirmDialogVisible}} <div cla ...

The bot believes it's jamming out to some tunes, but there's nothing but silence in the realm

Essentially, a slash command is utilized to initiate playing a music video in Distube. It plays for approximately 30 seconds and then abruptly stops, even though the queue indicates that the music is still playing. There are no errors appearing in my termi ...

There has been a mistake: The module '.... ode_modules erser-webpack-plugindistindex.js' cannot be found. Please ensure that the package.json file contains a correct "main" entry

After setting up Vue.js and executing npm run serve, I encountered the following error: PS C:\Amit\Demo\VUEDemo\myvue> npm run serve > <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="98f5e1eeedfdd8a8b6 ...

An error is being thrown by SetState when included within componentDidmount

I am currently learning React JS and have started working on a small application using it. I'm encountering an issue with the SetState method inside the componentDidMount lifecycle method. The scenario is that I have a parent/home component, which ca ...

Static response is the way to go! Asynchronous responses just don't cut it

Currently in the process of developing an angular directive for displaying real-time charts. Below is the code snippet that encompasses everything, including link: function() { }, within the directive. Here's the code for a static directive that func ...

Loading/Adding JS script in an asynchronous manner

In my Laravel project, I am implementing templates for different pages based on a main page. Each page requires different JS scripts to function properly, so I created a template to import these scripts: <!-- jQuery 2.1.3 --> <script src="{{ URL: ...

The try/catch block fails to execute or capture any errors

I'm attempting to create a help command that notifies users in case of closed DMs, but it's not working as expected. Despite encountering an error, the original messages are still sent instead of executing the catch function. I am relatively new ...

Learning the basics of JavaScript: Displaying the last number in an array and restarting a function

Hey there, I'm diving into the world of JavaScript and have set myself a challenge to create a simple bingo number machine. Check out my CodePen project here. I've successfully generated an array of 20 numbers, shuffled them, and added a marker t ...

Angular directive for concealing the 'ancestor' of an element

I have created a code snippet that effectively hides the 'grandparent' element of any '404' images on my webpage. Here is the code: function hideGrandparent(image){ image.parentNode.parentNode.style.display = 'none'; } < ...

Merging Vue props with v-for for powerful data handling

Below is an example of my child component HTML: <div v-for="(input, index) in form.inputs" :key="index"> <div> <input :name"input.name" :type="input.type" /> </div> </div> JavaScript (Vue): <script> export d ...

Leveraging Async / Awaits with Promise

Within my code, I have a specific promise chain that follows this structure: myPromise() .then(getStuffFromDb) .then(manipulateResultSet) .then(manipulateWithAsync) .then(returnStuffToCaller) An issue arises when working within the mani ...

Mastering the art of smooth transitions between three animation sequence states using three.js in the animate loop

I want to achieve smooth transitions for the three different wing flapping sequences within a short period of time. Currently, the transitions appear abrupt as they jump from one state to another. The wings have 3 distinct states: 1) On the ground, 2) Flyi ...

How can I implement a Component to show the details of a blog post when clicked in Next.js?

Can someone help me figure out how to display individual blog post details in a modal when clicked on in a blog website, where the posts are stored in a Component rather than pages? The file structure is set up like this: Component |_ Posts.js |_ PostDet ...

The reflight response received an unexpected HTTP status code of 500

Recently, I've been working on utilizing the Yelp Fusion API by making a simple ajax call. I started off by using the client_id and client_secret provided by Yelp to successfully obtain an access token through a 'POST' request in Postman, fo ...

JavaScript Function for Shuffling an Array

Looking for advice on optimizing a function I'm developing. My goal is to: Double the frequency of numbers in an array Randomize the location of the values in the array. For instance: Imagine I have an array. [0,1,2,3] First, I need to dupl ...