Storing $ Areas in a Factory

I am adding functionality to a web application that I did not write myself. I feel like the swipe function cannot be added.

I saw that "$ scope is not available in factory", but I somehow managed to keep all scopes created by ng-repeat in factory. Since JavaScript is passed by value, I'm probably not "preserving" scope, but still if I set scopes ng-class to a factory I can clearly see the difference. I thought it was a good idea since the scope is pain. Am I hitting gold or am I wasting speed and space storing massive data that is the domain?

Html

main.html

<div ng-controller="someCtrlWhichWasDeclaredALongTimeAgo">
    .
    .
    . 
    <div class="items-container"
         ui-sortable="sortableOptions"
         ng-model="selectedSession.items">
        <div ng-repeat="item in selectedSession.items"
             ng-controller="itemEditorCtrl"
             ng-class="{'item-last':$last}">
            <div ng-if="item._value !== undefined"
                 class="item inline-comment">
                <span class="handle"></span>
            </div>
            <div ng-if="item._value === undefined"
                 class="item"
                 ng-include="'/views/item-editor.html'"></div>
            </div>
        </div>

        <div class="stopper"></div>
    </div>
</div>

      

element-editor.html

<div item-editor
     swipe-function="swipeMe"
     ng-swipe-left="swipeLeft(item)" 
     ng-swipe-right="swipeRight(item)">
     ...
</div>

      

This will display a list with my magic code. Clicking on an item in the list expands it to full screen. You should be able to scroll items between them.

I don't think I should post more than HTML to explain the problem. I was able to do swipes using $ rootScope. $ Broadcast, but what if I have one hundred items in my list? Wouldn't it grow more slowly as more and more items receive the message and process them? I would rather just load all scopes into one factory when that session is selected and then get rid of it when the session is canceled. It may take a while to start, but it doesn't take 5 minutes to scroll.

+3


source to share


3 answers


What you are doing is perfectly normal. You can pass scope objects around your application as you see fit. Just keep in mind what they represent. An object $scope

is your interface with a view. In most cases, your services will have little to do with the view and should ideally be used to communicate between controllers and directives. However, there are a few examples where the general sense of service indirectly affects presentation. For example, we wrote a spinner service that allows spinner directives to register with the service.

The spinner directive injects into it spinnerService

, calls a function, spinnerService.register

and passes it to the allocation so that the service can track it and use it to turn the spinner on and off. Our developers can then inject the service where needed and hide / show the loading spinners or spinner groups when they need it.

What they mean by "$ scope cannot be accessed in a factory" is that you cannot inject $scope

inside a factory. $scope

is bound to a DOM element (the element that the controller or isolation directive was called on), so inserting a new one $scope

into the factory doesn't make much sense and is virtually impossible. You cannot do app.factory('myFactory', function ($scope) { ... });

, but you can definitely call your service factory / from a controller or directive and pass the scope object to where you provide the service.

There is nothing wrong with tracking services if you know what you are doing. People will tell you that you cannot pass your scope to the service because it is an anti-pattern, but then they will suggest to put something like this in your directive / controller and then pass it to the service:



var api = {
  hideSpinner: function () {
    $scope.show = false;
  },
  showSpinner: function () {
    $scope.show = true;
  }
};

      

Of course, you don't pass your object $scope

directly to the service, but if the argument is that the scope object can get stuck in memory and never be garbage collected, this solution won't help either. The API object that you create and pass includes JavaScript chaining with it, keeping in memory all variables within the scope it has defined, including $scope

your controller / directives. This is necessary or these API methods will not work. Yours $scope

is the API for that component and it's fine to use it that way.

The best argument for doing something like the above example is that perhaps your object $scope

contains information or functions that you don't need / want to use this service. Creating a small API object with just the things you want to expose to the service makes sense here. Then your service only has access to the things you want to access and can still affect the controller / directive $scope

, but only as described in the API object you passed.

+2


source


Please stay away from storing objects $scope

in any type of global storage. This includes $ rootScope and Angular Services.

Since services in Angular are single-handed, if any service keeps track of an object $scope

(in any service variable), it $scope

may never get released and there is a chance of a memory leak.



Also, the concept scope

is closely related to presentation and should not be used outside of this context.

Perhaps you can share some code around your implementation so that we can suggest a better solution.

+1


source


"$ scope cannot be retrieved in factory"

You're almost right. You cannot inject a service $scope

into another service. There's nothing stopping you from creating a service that stores data and putting $ scope as that data.

THIS IS A BAD IDEA . Services are used to exchange data between components. $scope

used to link to the view. Think of it like bananas and toasters. Both have their own goals, no one will blame you for using one or the other, but using a service to store $ scope is like filling a banana in a toaster.

Each component that uses $scope

should only be concerned with its own area - and no other (there are very rare exceptions, but you shouldn't use them if you don't know what you are doing).

Instead, put the data into services and then put the service data into scope:

.controller('ExampleController', function($scope, myService) {
  $scope.names = myService.names;
});

      

Better yet, you can study the controllerAs

syntax

0


source







All Articles