AngularJS组件中的参考服务变量

时间:2017-10-03 17:57:38

标签: angularjs

我是AngularJS的新手,并尝试使用该框架重做我之前应用程序的一些工作。我正在尝试在我的应用程序(AngularJS v1.6.6)中创建一个消息框服务,模块调用该服务以在UI中显示弹出窗口。

我似乎无法弄清楚如何将服务的变量绑定到UI本身。我已经尝试在控制器中创建一个本地'MessageBox'变量并引用它的内容,以及简单地调用注入的变量而没有运气。有什么方法可以通过服务实现这一目标吗?我在考虑一个全局变量,但我已经看到了反对这一点的建议。

服务似乎是最好的路线,但我愿意接受任何更有意义的建议。其他模块需要显示自己的错误或成功消息,所以我认为创建一种标准的方法来处理它会更容易。

我的代码如下:

消息box.template.html

<div id="message" ng-show="$ctrl.MessageBox.display" style="background-color: white; border: 1px solid black; margin: 5px; float: right; top: 60px; right: 2%; padding: 5px; position: fixed; z-index: 100;">
    <img id="message-image" height="30" width="30" alt="{{ $ctrl.MessageBox.Image.alt }}" ng-src="{{ $ctrl.MessageBox.Image.source }}" /> <span id="message-text">{{ $ctrl.MessageBox.text }}</span>
</div>

消息box.module.js

angular.module("components.message-box", ["components"])
    .controller("MessageBoxController", ["$scope", "MessageBox", function MessageBoxController($scope, MessageBox) {
    }]);

消息box.component.js

/**
 * message-box.component.js
 * Contains the 'message-box' component
 */
angular.module("components.message-box")
    .component("messageBox", {
        templateUrl: "/Scripts/cop/components/message-box/message-box.template.html",
        controller: "MessageBoxController"
    });

消息box.service.js

/**
 * message-box.service.js
 * Defines the 'message-box' service
 */

angular.module("components.message-box")
    .service("MessageBox", function () {
        var self = this;

        self.display = false;
        self.Image = {
            alt: null,
            source: null
        };
        self.text = null;
        self.timeout = null;

        /**
         * Hides the displayed message
         * @public
         */
        self.hideMessage = function () {
            self.display = false;
            self.timeout = null;
            self.Image.alt = null;
            self.Image.source = null;
            self.text = null;
        };

        /**
         * Displays the provided message to the user
         * @public
         * @param {string} text Message text
         * @param {Object} Image Image display data
         * @param {number} [hideTimeoutMs=null] Number of miliseconds to wait before hiding the message
         */
        self.showMessage = function (text, Image, hideTimeoutMs) {
            self.text = text;
            self.Image.alt = Image.alt;
            self.Image.source = Image.src;
            self.display = true;

            // Cancel timer for current timeout if it exists
            if (self.timeout !== null) {
                self.timeout = null;
            }

            // Set a new timeout if specified
            if (hideTimeoutMs !== undefined) {
                self.timeout = setTimeout(self.hideMessage, hideTimeoutMs);
            }
        };
    });

以下是尝试调用服务的示例:

visual.module.js

angular.module("core.visual", [
    "ngRoute",
    "core.visual.settings"
])
    .controller("VisualController", ["$routeParams", "$scope", "MessageBox",
        function VisualController($routeParams, $scope, MessageBox) {
            var self = this;
            self.MessageBox = MessageBox;
            
            self.MessageBox.showMessage("This is a message", "/Content/Images/loading.png", "Loading", 10000);
        }
    ]);

我也尝试过不使用MessageBox作为本地控制器变量而没有成功 - 这只是我最近的尝试。

我是否在正确的轨道上?这甚至可能吗?

1 个答案:

答案 0 :(得分:0)

我发现了this问题,这有助于我找到答案。

以下是我对MessageBox服务所做的更改。我能够在不改变服务功能调用方式的情况下完成所有工作。

<强>消息box.service.js

&#13;
&#13;
/**
 * message-box.service.js
 * Defines the 'message-box' service
 */

angular.module("components.message-box")
    .factory("MessageBox", ["$rootScope", "$timeout", function ($rootScope, $timeout) {
        var self = {};

        // Declare the Message variables
        self.display = false;
        self.imageSrc = null;
        self.text = null;
        self.timeout = null;

        /**
         * Hides the displayed message
         * @public
         */
        self.hideMessage = function () {
            // Nullify all properties
            self.display = false;
            self.imageSrc = null;
            self.text = null;
            self.timeout = null;
        };

        /**
         * Displays the provided message to the user
         * @public
         * @param {string} text Message text
         * @param {Object} imageSrc Image source location
         * @param {number} [hideTimeoutMs=null] Number of miliseconds to wait before hiding the message
         */
        self.showMessage = function (text, imageSrc, hideTimeoutMs) {
            self.text = text;
            self.imageSrc = imageSrc;
            self.display = true;

            // Set a new timeout if specified
            if (hideTimeoutMs !== undefined) {
                self.timeout = hideTimeoutMs;
            }
            else {
                self.timeout = null;
            }

            // Broadcast changes
            // Use a timeout so messages don't fail before controller instantiation
            $timeout(function () { $rootScope.$broadcast("message:updated", self); });
        };

        return self;
    }]);
&#13;
&#13;
&#13;

最大的变化是不在这里处理超时而是保持值;该服务现在在对消息进行更改时进行广播,并由以下控制器处理。

我仍然使用hideMessage()清除局部变量以保持一致性。我还删除了&#39; alt&#39;属性,因为我无法弄清楚如何让Angular管理该值(使用{{}}似乎无法正常工作)。

此处使用的$ timeout会在广播更改之前稍微延迟。在某些情况下,如果在控制器中立即调用showMessage()(在完全构造之前),则不会显示该消息,因此这将修复该消息。在较大的应用程序中,这可能还不够,但这相对较小。

大部分更改都在组件的控制器中:

<强>消息box.module.js

&#13;
&#13;
/**
 * message-box.module.js
 * Defines the 'components.message-box' module
 */

angular.module("components.message-box", ["components"])
    .controller("MessageBoxController", ["$scope", "MessageBox", function MessageBoxController($scope, MessageBox) {
        // Listen for message changes
        $scope.$on("message:updated", function (evt, data) {
            // Update global message variable
            $scope.$apply(function () {
                $scope.Message = data;
            });
            // Check for a timeout
            if (data.timeout !== null) {
                setTimeout(function () {
                    $scope.$apply(function () {
                        data.hideMessage();
                    });
                }, data.timeout);
            }
        });
    }]);
&#13;
&#13;
&#13;

控制器现在侦听消息更新事件。当发生这种情况时,控制器使用$ apply用新消息替换范围值,以便UI也更新。同样,它现在处理消息消失的超时值(如果适用),并且还使用$ apply,因为UI仍然需要知道何时不再显示消息。

<强>消息box.template.html

&#13;
&#13;
<div id="message" ng-show="Message.display" style="background-color: white; border: 1px solid black; margin: 5px; float: right; top: 60px; right: 2%; padding: 5px; position: fixed; z-index: 100;">
    <img id="message-image" height="30" width="30" alt="Information" ng-src="{{ Message.imageSrc }}" /> <span id="message-text" ng-bind="Message.text"></span>
</div>
&#13;
&#13;
&#13;

message-box.component.js 未发生变化)

希望这可以帮助处于类似情况的人。这个解决方案对我有用,但如果有更好的方法来解决这个问题,请告诉我。