The battle between AngularJS, Factory, $scope, and promises intensifies

Currently facing a challenge with the code snippet below:

app.factory('sfAttachment', ['$http', '$q', '$window', '$rootScope', function($http, $q, $window, $rootScope) {

  var attachment = {};
  //Function to save attachments to the server
  attachment.save = function(base64value, document, index) {

    //Removing unnecessary file type text from the base64 value
    var position = base64value.indexOf("base64,");
    var matchWord = "base64,";
    var base64valueClean = base64value.slice(position + matchWord.length, base64value.length);

    //Data payload for saving in SF database
    var data = {
      "Body": base64valueClean,
      "ContentType": document.attachmentContentType,
      "ParentId": document.id,
      "Name": document.fileName
    };

    //Getting the URL value for posting to SF database
    var url = $window.__url;
    var method = 'POST';

    var request = {

      url: url,
      method: method,
      data: data,
      headers: {
            __XHR__: function() {
                return function(xhr) {
                    xhr.upload.addEventListener("progress", function(event) {

                      $rootScope.text = event.loaded/event.total;
                      $rootScope.$apply();
                        console.log("uploaded " + ((event.loaded/event.total) * 100) + "%");

                    });
                };
            }
        }
    };

    console.log(request);

    //Using promise approach for HTTP request
    var deferred = $q.defer();

    //Making HTTP request to the server
    $http(request).then(function(response) {

      deferred.resolve(response);
      console.log('File UPLOADED to SF!');

    }, function(event) {

      //Improvements needed in error handling
      deferred.reject('The attachment could not be saved:' + event);

    });


    return deferred.promise;
  }

This service successfully loads an Attachment into Salesforce. I added code

headers: {
    __XHR__: function() {
        return function(xhr) {
          xhr.upload.addEventListener("progress", function(event) {

            $rootScope.text = event.loaded / event.total;
            $rootScope.$apply();
            console.log("uploaded " + ((event.loaded / event.total) * 100) + "%");

          });
        };

to monitor upload progress and it displays the percentage in the console. Now, I want to pass this progress percentage to the controller that calls this service. I'm having trouble figuring out how to grab the text properly, currently using $rootScope.text and setting up a watch in my controller. It works, but is there a better way to achieve this?

$rootScope.$watch('text', function(newValue, oldValue, scope) {
  console.log($rootScope.text);
});

Answer №1

Angular's $q promises offer a feature for progress updates. You can create a promise like this:

app.factory('sfAttachment', [
    '$http', '$q', '$window', '$rootScope', function ($http, $q, $window, $rootScope) {

        var attachment = {};
        //Save function for attachments
        attachment.save = function (base64value, document, index) {

            /*Stripping file type text from base64 string to avoid corruption */
            var position = base64value.indexOf("base64,");
            var matchWord = "base64,";
            var base64valueClean = base64value.slice(position + matchWord.length, base64value.length);

            //Data payload for SF database save
            var data = {
                "Body": base64valueClean,
                "ContentType": document.attachmentContentType,
                "ParentId": document.id,
                "Name": document.fileName
            };

            /*Get the {!URLFOR('/services/data/v26.0/sobjects/Attachment/')} value
              cannot be processed on static ressource, hence the link to the window
              global variable.*/
            var url = $window.__url;
            var method = 'POST';

            var deferred = $q.defer();

            var request = {
                url: url,
                method: method,
                data: data,
                headers: {
                    __XHR__: function () {
                        return function (xhr) {
                            xhr.upload.addEventListener("progress", function (event) {
                                var pct = event.loaded / event.total;
                                // notify here
                                deferred.notify(pct);
                                console.log("uploaded " + (pct * 100) + "%");
                            });
                        };
                    }
                }
            };

            $http(request).then(function (result) {
                deferred.resolve(result);
            }, function (error) {
                deferred.reject(error);
            });

            return deferred.promise;
        };

        return attachment;
    }
]);

Consuming the promise can be done like this:

sfAttachment.save(value, document, index)
    .then(function (result) {
        console.log('finished downloading');
    },
    null,
    function (pct) {
        $scope.downloadPct = pct;
    })
    .catch(function (error) {
        console.log('oh noes!');
    });

Chaining two file uploads:

sfAttachment.save(file1, document, index)
    .then(function (result) {
        return sfAttachment.save(file2, document, index);
    }, null, function (pct) {
        $scope.downloadPct = pct;
    })
    .then(null, null, function (pct) {
        $scope.downloadPct2 = pct;
    })
    .catch(function (error) {
        console.log('oh noes!');
    });

Answer №2

If you're looking for a solution, consider using the $broadcast function. There's a great explanation on this topic in the following post: $on and $broadcast in angular

For more information on $broadcast and $on, check out the documentation here

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

Using AngularJS ng-repeat with jQuery find yields a single element result

I'm in the process of developing my very first AngularJS application, and I've run into an issue with the jQuery find function. Essentially, what I'm attempting to do is utilize a custom HTML component that contains a list of buttons generat ...

Select elements in jQuery using both a specific selector and a negative selector

I am currently working with a JQuery function that highlights a specific word and scrolls to it: $('article.node--article p, .video-title').highlightWordAndScroll({ words : search_word, tag : '<span class="found_key ...

How can I create a menu of buttons in Vue that open individual windows with unique URLs when clicked?

Javascript Code: function InitializeVue() { var vueOptions = { el: '#activeEvents', data: { activeEvents: [] } }; vueInstance = new Vue(vueOptions); } HTML Code: <table id="activeEvents"> ...

Tips for adjusting column sizes in react-mui's DataGrid based on screen size

I would like the title column to occupy 3/4 of the full row width and the amount column to take up 1/4 of the full row width on all screens sizes (md, sx...). Here is the updated code snippet: import React from 'react' const MyComponent = () =&g ...

Ways to update parent and ancestor windows following the closure of child windows

My scenario involves three windows in a hierarchy: 1st - the main window 2nd - a child window that is opened using window.showModalDialog from the 1st window. 3rd - a window that is an ancestor of the 1st window and is opened from the 2nd window using ...

Organizing data in a database the arrangement way

I'm looking to populate an array with values for "name" and "nickname" extracted from an SQLITE database and then display them in an alert box. This task is part of a JavaScript project developed using Titanium Appcelerator. Below is the code snippe ...

Receiving a reply but failing to give a response

My code is causing an ERR_HTTP_HEADERS_SENT error. Can you help me identify what's wrong with it? .then((userDetails: any) => { userDetails.role.forEach((singleRole) => { if (singleRole.name === 'admin&apos ...

Enhancing React Flow to provide updated selection and hover functionality

After diving into react flow, I found it to be quite user-friendly. However, I've hit a roadblock while attempting to update the styles of a selected node. My current workaround involves using useState to modify the style object for a specific Id. Is ...

Utilizing a jQuery AJAX request to invoke a web method within a

My goal is to integrate jQuery mobile into an existing ASP.NET webform application. I am currently considering using pure HTML controls to create the jQuery Mobile page. I am aware that when making an AJAX call, I can access code-behind static web methods, ...

Angular and Bootstrap4: The Perfect Duo for Modals

I need to display a Bootstrap4 modal window in Angular when a specific condition is met in my "bookTour" method without the need for a direct button click. How can I achieve this? Below is the code snippet: html <div class="modal" id="myModal" [ngClass ...

How can I handle a 404 error if an object is not found in a JSON file?

Below is my code snippet where I check for the correct req.path and display specific text. However, I now need to show a 404 not found error message. I attempted placing it inside the for loop condition with break;, but it's not quite working as expe ...

Error 404: Node.js and Express encountering issues with POST request to '/webhook' endpoint

https://i.sstatic.net/CTDCv.pnghttps://i.sstatic.net/KjPeC.pngI've encountered a peculiar issue where I keep receiving a 404 error specifically when sending a post request to '/webhook'. This error is persistent even though the rest of my po ...

I am constantly encountering the error message "Reading 'Linear'' error due to undefined properties in my threejs code

A procedural generation library for threejs caught my attention Here is the link to the library: https://github.com/IceCreamYou/THREE.Terrain Despite following the instructions provided in the ReadMe.md file, I encountered an error that says: Cannot read ...

When attempting to clear a specific word or character, the entire text is cleared instead

Currently, I am utilizing fabric js along with reactjs to incorporate text onto the canvas. While the text is successfully added, I encountered an issue when attempting to clear specific characters or selected words, resulting in the whole text being cle ...

Analog Clock Time Adjustment Bubble Deviation Dilemma

Recently, I encountered an issue with an analog clock component. Every time I click on the time adjustment bubble repeatedly while also moving the cursor position, it tends to drift away from its original placement, which should ideally be between an orang ...

Clicking on the mail icon will open the mail with the associated mail id

https://i.sstatic.net/6TLpN.pngWhen the mail icon is clicked, the mail will open with this email address. I am currently working on a project where clicking the mail icon will redirect to the mail signup page with the corresponding email address. In the ...

What is the method for altering the color of the webkit-slider-thumb using JavaScript?

I am looking to adjust the color of an input range using JavaScript instead of CSS. Can someone help me with this request? Current CSS Code: input[type='range']::-webkit-slider-thumb { -webkit-appearance: none; background: goldenrod !importa ...

Guide to ensuring jQuery Ajax requests are fully processed with WatiN

Currently, I am in the process of developing WatiN tests to evaluate an Ajax web application. However, I have encountered a timing issue with Ajax requests. My main objective is to ensure that WatiN waits for the Ajax request to be completed before valida ...

Having trouble receiving the response from PHP after making an AJAX request

Can you help me figure out why I'm not receiving any return value from the ajax data post? Take a look at my code and let me know where I might be going wrong. Here is a snippet of my jQuery code: $("#btnlogin").click(function(){ var email = $( ...

Retrieve the id of an element from a JSON object

Dealing with quotes, single or double, can sometimes pose a challenge. I am working on a JavaScript function that sends data to a PHP file and receives a JSON response. Everything seems to be functioning correctly, except for the part where I need to out ...