Is it possible to bind to a service variable in a controller without using $scope and utilizing the

As I delve into the world of controllerAs syntax in AngularJS, I've encountered a snag when attempting to bind a service variable. The traditional approach using `$scope.$watch` or `$scope.$on` would require injecting `$scope`, which seems counterintuitive to the essence of controllerAs.

Currently, I am facing an issue where after clicking a button and invoking `config.setAttribute(attr)`, the controller triggers the service's `setAttribute` function but not `getAttribute`. As a result, `config.attribute` remains unchanged.

Am I missing something in my approach? Would it be necessary to inject `$scope` or switch to using `$scope` in the controller syntax instead?

View:

<div data-ng-controller="ConfigCtrl as config">
    <h3>Customize</h3>
    <pre>Current attribute: {{config.attribute}}</pre>

    <label>Attributes</label>
    <div data-ng-repeat="attr in config.attributes">
        <button ng-click="config.setAttribute(attr)">{{attr.name}}</button>
    </div>
</div>

Service:

(function() {
'use strict';

angular.module('app')
.factory('Customization', Customization);

function Customization() {
    var service = {
        attribute: null,
        getAttributes: getAttributes,
        setAttribute: setAttribute,
        getAttribute: getAttribute
    }
    return service;
    /////
    function getAttributes() {
        return [
            {name: 'Attr1', value: '1'},
            {name: 'Attr2', value: '2'} // etc.
        ];
    }

    function setAttribute(attr) {
        service.attribute = attr;
    }

    function getAttribute() {
        return service.attribute;
    }
}})();

Controller:

(function(){
'use strict';

angular.module('app')
.controller('ConfigCtrl', ConfigCtrl);

function ConfigCtrl(Customization){
    var vm = this;

    vm.attribute = Customization.getAttribute(); // bind
    vm.attributes = [];

    // Functions
    vm.setAttribute = Customization.setAttribute;

    init();
    /////
    function init(){
        // Get attributes array
        vm.attributes = Customization.getAttributes();
    }
}})();

Answer №1

Here's a snippet of my controller where I've included $scope and set up a watch for the attribute:

(function(){
'use strict';

angular.module('app')
.controller('ConfigCtrl', ConfigCtrl);

function ConfigCtrl($scope, Customization){
    var vm = this;

    vm.attribute;
    vm.attributes = [];

    // Functions
    vm.setAttribute = Customization.setAttribute;

    init();
    /////
    function init(){
        // Retrieve attributes array
        vm.attributes = Customization.getAttributes();
    }

    $scope.$watch(function() {
        return Customization.getAttribute()
    }, function() {
        vm.attribute = Customization.getAttribute();
    });

}})();

For those curious, here's the Karma test as well:

(function() {
    'use strict';

    describe('ConfigCtrl', function () {

        var ConfigCtrl, scope;

        beforeEach(module('app'));

        beforeEach(inject(function($rootScope, $controller) {
            scope = $rootScope.$new();
            ConfigCtrl = $controller('ConfigCtrl',
                {$scope: scope}
            );
        }));

        describe('#setAttribute', function(){
            it('sets the current attribute', function(){
                var selected = {
                    name:'Attr1',
                    value:'1'
                };
                ConfigCtrl.setAttribute(selected);
                scope.$apply();
                expect(ConfigCtrl.attribute).to.eql(selected);
            });
        });
    });
})();

Appreciate the assistance. Open to other suggestions for improvement as well.

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 is the method to activate map dragging in Leaflet only while the spacebar is pressed?

When using Leaflet maps, the default behavior is to drag the view around by only clicking the mouse. However, I am interested in enabling dragging with the mouse only if the spacebar is pressed as well. I would like to reserve mouse dragging without the sp ...

Encountering a 404 error while using Angular HTML5Mode setting

I recently enabled pretty URLs in my Angular application by switching to html5mode. However, whenever I try to refresh the page, I encounter a 404 error. For instance, if I access my app through , everything functions as expected. But when I attempt to r ...

Creating scalable React applications

Can you provide insights on the scalability of React Apps? What recommended approaches are typically employed to effectively handle and generate scalable states in web applications using Reactjs? * ...

Adjust the zoom level when a location is detected using Mapbox

I have been reading through the leaflet documentation and it mentions using the maxZoom option for location, but I am having trouble getting it to work (http://leafletjs.com/reference.html#map-locate-options). Whenever a user uses geolocation on my websi ...

Checking for the presence of text within a span tag - a simple guide

see fiddle if there is an already allotted time slot for the patient, change its color to yellow using jquery on the client side. In my example, if I assign a time slot for the first time, it turns green and when assigning another one, the previous slot tu ...

Tips for aggregating the values of object arrays in React props

I need help sorting three top-rated posts. Currently, the function displays three post titles along with their ratings, but they are not sorted by best rating. Can anyone assist me with this issue? {posts.slice(0, 3).sort((a, b) => ...

Is it possible to incorporate FCM into Next.js and effectively handle server-side events for FCM on Next.js servers?

Is it feasible to incorporate the Firebase Cloud Messaging (FCM) into my upcoming Next.js application? Can I manage both client-side and server-side modules within the server side? ...

How to utilize the ng-disable feature in AngularJS when using ng-repeat

In my current JavaScript code, I have two arrays of objects. The first array, named list1, consists of objects with keys "show" (boolean) and "number" (integer). The second array, named list2, only contains an integer key named "number". There is a button ...

Why aren't the divs appearing on the page?

I have developed a JavaScript and PHP page where the script in the PHP page sends data to my SQL database. However, the result is not displayed on my home page. Here is the code snippet: function getVote(question_ID) { var option_ID = document.queryS ...

I am encountering a problem where I lose the values of a nested array of objects when trying to push it into another array

My goal is to format data for use with the amCharts library. The required structure should look like this: data = [{ name: "First", total: 190, children: [ { name: "A1", value: 100 }, { name: &q ...

Retrieve the string data from a .txt document

I am facing an issue with my script that retrieves a value from a .txt file. It works perfectly fine when the value is a number, but when trying to fetch text from another .txt file, I encounter the "NaN" error indicating it's not a number. How can I ...

Attempting to convert a Raw image file and upload it onto the server

I am currently attempting to upload an image to my server using PHP. I have two files for this task - index.php and myscript.php. Index.php <div id="results">Your captured image will appear here...</div> <h1>Mugshot Test Page& ...

JavaScript tool: Verify the presence of both jQuery and jQuery UI

I have been working on developing a Javascript Widget (almost complete), and when integrating it into the first site I encountered some issues. My Widget requires loading multiple libraries (jquery, jquery ui, mustache, ...); this is achieved by injecting ...

Say goodbye to document.write?

There is a function defined below: function loadJavaScript(src) { document.write('<' + 'script src="' + src + '"' + ' type="text/javascript"><' + '/script>'); } This ...

Are there any alternatives to ui-ace specifically designed for Angular 2?

I am currently working on an Angular2 project and I'm looking to display my JSON data in an editor. Previously, while working with AngularJS, I was able to achieve this using ui-ace. Here is an example of how I did it: <textarea ui-ace="{ us ...

The integration of Angular 6 with AngularJS components fails to load properly in a hybrid application

Currently, I am in the process of upgrading a large AngularJS version 1.7.3 to a hybrid app using Angular 6. The initial phase involved converting all controllers/directives into an AngularJS component. Subsequently, I created a new Angular 6 project skele ...

hierarchical browsing system

Take a look at the image provided below. Currently, I am using multiple unordered lists - specifically 5. However, I would prefer to consolidate them all into a single nested ul. I am encountering two issues: How can I add a border-bottom to the hori ...

How can we effectively manage error responses and retry a failed call in NodeJS without getting tangled in callback hell?

I am in search of an effective approach to handle the given situation. I am curious if employing promises would be a helpful solution? Situation Overview: When a call retrieves a callback, and this callback receives an error object as a parameter. My obj ...

Having trouble with linking an external JavaScript file inside the head tag?

I've connected my script.js file to my index.html file, and both files are located in the same directory. I initially linked the script.js file in the <head> section, but it wasn't working as expected. Upon checking the console, I encounter ...

Change the spread operator in JavaScript to TypeScript functions

I'm struggling to convert a piece of code from Javascript to Typescript. The main issue lies in converting the spread operator. function calculateCombinations(first, next, ...rest) { if (rest.length) { next = calculateCombinations(next, ...res ...