如何用Angular的方式将更新后的对象从Service发送到指令控制器函数

How to send updated object from Service into Directive Controller function the Angular way?

本文关键字:Service 指令控制器 函数 Angular 何用 方式 更新 对象      更新时间:2023-09-26

我知道我错过了AngularJS正确执行此操作的方法。

在我的tagsPanel的视图mouseover上,我捕获标签对象并首先将其发送到我的tagsPanel控制器:

tagsPanel.html

<ul>
    <li ng-repeat="(k, m) in tags"
        ng-mouseover="hoverTag(m)"
        ng-mouseleave="leaveTag(m)">
        <div class="tag">{{m.term}}</div>
        <tags-hover ng-model="m"></tags-hover>
    </li>
</ul>

tagsPanel控制器:

vs.hoverTag = function(tagObj) {
    TagDetailsFactory.saveTagDetails(tagObj);
};

tagDetailsFactory 工厂的最后一步是我所关心的:

tagsHover = ScopeFactory.getScope('tagsHover');
tagsHover.hoveringTag(tag);

完整工厂代码:

(function() { "use strict";
    angular.module('tagDetailsFactory', [])
    .factory('TagDetailsFactory', [
        'ApiFactory',
        'ScopeFactory',
        function(ApiFactory,
                 ScopeFactory) {
        // Init ScopeFactory:
        // ------------------
        var tagsHover = {};
        return {
            saveTagDetails : saveTagDetails
        };
        ////////////////////////////////////////////////////////////////////////
        function saveTagDetails(tag) {
            if (tag.percent != undefined) {
                var conditional = tag.percent.toString().charAt(0);
                tag.direction = returnDirection(conditional);
            }
            function floorFigure(figure, decimals) {
                if (!decimals) decimals = 2;
                var d = Math.pow(10, decimals);
                return (parseInt(figure * d)/d).toFixed(decimals);
            };
            ApiFactory.getTagData(tag.term_id).then(function(data) {
                /*
                    Ton of tag updating code here
                    // Algorithm to get percentage change:
                    increase = tag.quantity - tag.previous_quantity;
                    increase = increase / tag.previous_quantity * 100;
                    increase = floorFigure(increase, 2);
                    etc etc...
                 */
                tagsHover = ScopeFactory.getScope('tagsHover');
                tagsHover.hoveringTag(tag);
            });
        };
    }]);
})();

^正如你在上面看到的,我粗略地抓住了tagsHover指令的作用域,然后瞄准其中的一个函数,并传递更新的tag对象。


下面是我的整个tagHoverDirective标记,理想的Angular方式将更新的标签对象传递到tagHoverDirective函数hoveringTag中?

(function() { "use strict";
    angular.module('tagHoverDirective', [])
    .directive('tagsHover', function() {
        return {
            templateUrl : "tags/tagsHover.html",
            restrict    : "E",
            replace     : true,
            link: function($scope, el, attrs) {
                // console.debug($scope, attrs);
            },
            scope:{
                tag:'=ngModel'
            },
            controller  : ['$scope',
                           'ScopeFactory',
                           'TagDetailsFactory',
                           function($scope,
                                    ScopeFactory,
                                    TagDetailsFactory) {
                // Init tagsHover scope:
                // ---------------------
                var vs = $scope;
                    ScopeFactory.saveScope('tagsHover', vs);
                vs.hoveringTag = function(t) {
                    t.tagsHoverDisplay = true;
                };
                vs.leavingTag = function(t) {
                    t.tagsHoverDisplay = false;
                };
            }]
        }
    });
})();

标记tagHover.html

<div class="tags-hover-container" ng-show="tag.tagsHoverDisplay">
    <div class="tag-info-padding">
        <div class="tweets" ng-hide="!tag.quantity">
            <div class="percentage" ng-hide="tag.length">
                {{tag.tweet_percentage}}%
            </div>
            <div class="tweet-count">{{tag.quantity}} tweets</div>
        </div>
        <div class="tweets-direction" ng-show="!tag.quantity">
            0 tweets
        </div>
    </div>
</div>

我编写了一个基本的例子,根据它感兴趣观察的标签类型,通过回调通知指令更新。我放了三个文本域,标识符文本域才是真正重要的。

首先是标记,这只是一个空指令,它的模板将在没有标记数据的情况下呈现,表单将标记我们将要存储的值。

<sample-directive></sample-directive>

<form ng-submit="addNewTag()">
    <input placeholder="tag type identifier" type="text" ng-model="tag.tagIdentifier">
    <input placeholder="tag name" type="text" ng-model="tag.tagName">
    <input placeholder="tag message" type="text" ng-model="tag.tagMessage">
    <input type="submit" value="Add new tag">
</form>

添加标签的控制器

.controller('mainCtrl',function($scope, sampleService) {
$scope.tag = {
    tagName: "",
    tagIdentifier: "",
    tagMessage: ""
}
$scope.addNewTag = function() {
    var tag = {};
    tag.message = $scope.tag.tagMessage;
    tag.name = $scope.tag.tagName;
    sampleService.setTag(tag, $scope.tag.tagIdentifier);
}
})

主要思想在这里

.directive('sampleDirective', function(sampleService) {
return {
    restrict: 'E',
    link: function(scope, iElement, iAttrs) {
        sampleService.registerTagCallback("tagsHover",tagCallback);
        function tagCallback(tag) {
            scope.tag = tag;
        }
    },
    template: "<div>{{tag.message}}</div>"
}
})

这个指令(当它被注册并且它的link函数被激活时)将使用该服务来注册一个回调,当你在工厂内部设置一个标签时,这个回调应该在工厂内部执行。可以这样做

.service('sampleService', function() {

return {
    setTag: setTag,
    registerTagCallback, registerTagCallback
}
var callbacks;
var tags;
function setTag(tag, identifier) {
    if (!tags || tags.length == 0)
        tags = [];
    tags.push({
        tag: tag,
        identifier: identifier
    });

    angular.forEach(callbacks, function(callback) {
       if (callback.identifier == identifier) {
          callback.method(tag);
       }
    });

}

function registerTagCallback(identifier, callback) {
    if (!callbacks || callbacks.length == 0)
        callbacks = [];
    callbacks.push({
        identifier: identifier,
        method: callback
    });
}
}) 

每次设置标记时,检查已注册的回调,看看是否有人对接收该标记感兴趣,并使用传入的标记调用该回调。然后,指令在内部从注册的回调函数参数更新它的作用域。

这是我把一个小提琴和一个工作示例放在一起。标签标识符需要匹配指令的回调标识符(在本例中是"tagsHover"),那么你应该看到带有标签

的名称和消息的指令更新。https://jsfiddle.net/5c88pte6/4/