Changing $scope within an AngularJS service

I am currently working on an application that utilizes the Gmaps API for geolocalization. One of the challenges I faced was adding new markers based on user events. To address this, I created a service that listens to map events and adds markers when clicked. However, I encountered difficulty in modifying certain $scope properties within this service. Below is an example of the service I have developed:

climbingApp.factory('Markers', function(){
    return {
        addListener: function() {
            google.maps.event.addListener(
                map,
                'click',
                 function( e ) {
                    var marker = new google.maps.Marker({
                        position: e.latLng,
                        map: map
                    });

                }
            );
        }
    }
});

I am seeking guidance on how to retrieve the value of e.latLng and use it to update a specific $scope property. Any advice would be greatly appreciated.

Answer №1

According to @Ajaybeniwal, it is advised not to manipulate the scope outside of a controller. One way to handle this is by modifying addListener to accept a callback function:

climbingApp.factory('Markers', function($rootScope) {
    return {
        addListener: function(callback) {
            google.maps.event.addListener(map, 'click', function(e) {
                $rootScope.$apply(function() { callback(e); });
            });
         }
    }
});

With this change, you can now incorporate it like so within your controller:

Markers.addListener(function(e) {
    $scope.model.position = e.latLng;
});

An alternative approach is using promises instead of callbacks:

climbingApp.factory('Markers', function($rootScope, $q) {
    return {
        addListener: function() {
            var deferred = $q.defer();
            google.maps.event.addListener(map, 'click', function(e) {
                $rootScope.$apply(function() { deferred.resolve(e); });
            });
            return deferred.promise;
         }
    }
});

In this scenario, your controller would be structured in the following way:

Markers.addListener().then(function(e) {
    $scope.model.position = e.latLng;
});

Promises offer an advantage over callbacks as they can be directly bound to a view, and Angular will update the value automatically once it's ready. For more insights on this topic, refer to this post.

Lastly, it's crucial to remember that you must call $rootScope.$apply() in both instances to prompt Angular to initiate a digest cycle for proper processing. This step is necessary because Angular remains unaware of google.maps.event.addListener, therefore, it won't receive notification when the gmaps callback is executed.

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

group items into ranges based on property of objects

I've been grappling with this issue for far too long. Can anyone provide guidance on how to tackle the following scenario using JavaScript? The dataset consists of objects representing a date and a specific length. I need to transform this list into a ...

Retrieving information from an Angular service using a specified function

I have been working on accessing data from a method within a service that returns coordinates, which are used to make HTTP requests in my application. I have integrated my Leaflet code into the controller to be able to access the lat,lng coordinates for ...

passport.authenticate method fails due to empty username and password values

I seem to be making a simple mistake while following a tutorial. Even though I believe I have followed all the steps correctly, when I submit the login form, I get redirected to the "failureRedirect" page. When I checked the source code in the passport mod ...

Having trouble with finding the correct object in an array of objects using indexOf and splice()?

Here is an example of an array of objects: "followers": [ { "id": "1be87842-2f7f-4e3b-8fde-9a998feb3a01", "bug_id": "4ae2707b-07ef-4e07-95da-77855c67fece", "user_id": "e9e81aa2-4994-483d-a3a7-3b88491f1fda", ...

problem with maximum width in Internet Explorer 8

Struggling with a compatibility issue in IE8. Here's my HTML code - Test in any browser and then try in IE8 jsfiddle.net/G2C33/ The desired output should be like this The problem is that the max-width property doesn't work in IE8. Note: Test ...

Importing a file using its absolute path in JavaScript

Within the dependencies directory, there exists a module named foo: import foo from '../dependencies/foo'; // This import statement works as intended The challenge arises when attempting to import from a different path due to deployment in an AW ...

How can I locate the element immediately preceding $(this)?

Struggling to retrieve the value of the $(.subname) when the .bigadminbutton is clicked and calling the updateSub() function. I have tried various methods like prev, sibling, parent, children, find, but none seem to work. This minor task is taking up too ...

Is it possible to load HTML content within a Sweet Alert pop-up

Below is the code I am using to call Swal: window.swal({ title: "Checking...", text: "Please wait", imageUrl: "{{ asset('media/photos/loaderspin.gif') }}", showConfirmButton: false, allowOutsideClick: false }); $.ajax({ t ...

Learn how to incorporate the dynamic array index value into an Angular HTML page

Exploring Angular and facing a challenge with adding dynamic array index values in an HTML page. Despite trying different solutions, the answer remains elusive, as no errors are being thrown. In TypeScript, I've initialized an array named `months` wh ...

Learn the process of adding a key and value into an array using Angular

I need to filter data based on the number of rows and columns provided by the user. After reading an excel file, I extract the data in the controller: https://i.sstatic.net/vPpxL.png These are the column headers retrieved after the user entered 5 as the ...

I encountered an issue while constructing a React application. An error message popped up indicating: "Warning: Can't execute a React state update on a component that is not mounted"

Having difficulty pinpointing the source of the error message displayed below. Should I focus my investigation on the specific lines mentioned in the console, such as Toolbar.js:15? Is the console indicating that the error lies there? Additionally, what i ...

Discovering ways to fetch an array of objects using object and arrays in JavaScript

When comparing an array of objects with a single object and listing the arrays in JavaScript, specific conditions need to be met to retrieve the array of objects: If the itemvalue and idvalue are the same, check if the arrobj cid has the same codevalue ...

Analyzing JSON data and creating a tailor-made array

My Dilemma { "rowId": "1", "product_name": [ "Item A", "Item B", "Item C", "Item D", "Item E" ], "product_tag": [ "123456", "234567", "345678", "456789", "5678 ...

The process by which Expressjs determines the appropriate error handler to execute when multiple error handlers are present

I've been wondering, how does Express decide which error handler to call (next(err)) when there are multiple error handlers in place? ...

Unable to show the response from an HTML servlet using Ajax and qTip2

I am having an issue where I am trying to display text (or html) received from a servlet response in a qTip2 tooltip within a jsp page. Despite verifying that the servlet is being invoked and returning text using Firebug, I encountered an error when attemp ...

PHP header malfunctioning post AJAX request triggered by JavaScript

Hey there, I have a query that might sound silly to some, but I'm curious if it's feasible to utilize the header function within a php file when receiving an AJAX response. In my scenario, I'm working on a login form where I use AJAX to com ...

Guide on implementing the 'cut' feature using electron-localshortcut

Looking for a way to use keyboard shortcuts on Mac without relying on the menu? I recently came across this helpful post: Is it possible to create non-global accelerators without adding them to a menu? Thanks to this informative article, I learned about ...

Issue: Login form in AngularJS does not reset upon page reload

I have developed a login form using AngularJS. Below is the HTML code: <div class="container" ng-controller="loginCtrl"> <div class="card card-container" > <img id="profile-img" class="profile-img-card" src="//ssl.gstatic.com/ac ...

Issue with PrimeFaces radiobutton styles not updating after being clicked programmatically

My setup includes a p:selectOneRadio constructed like this: <p:selectOneRadio id="positionRadio" value="#{employeeBean.empPosition}" converter="#{empPositionConverter}" layout="custom" required="true" requiredMessage="Please select ...

Having trouble activating the Invalidate Cache function in rtk query with tags

Here is a snippet from my Api.js file: export const api = createApi({ reducerPath: 'api', baseQuery: fetchBaseQuery({ prepareHeaders: (headers, { getState }) => { const userInfo=JSON.parse(localStorage.getItem('userInfo' ...