【问题标题】:Reference Service Variable in AngularJS Component在 AngularJS 组件中引用服务变量
【发布时间】:2018-03-15 00:10:41
【问题描述】:

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

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

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

我的代码如下:

message-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>

message-box.module.js

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

message-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"
    });

message-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 作为本地控制器变量,但没有成功 - 这只是我的最新尝试。

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

【问题讨论】:

    标签: angularjs


    【解决方案1】:

    我找到了this 问题,它帮助我找到了答案。

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

    message-box.service.js

    /**
     * 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;
        }]);

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

    为了保持一致性,我仍在使用 hideMessage() 清除局部变量。我还删除了“alt”属性,因为我不知道如何让 Angular 管理该值(使用 {{}} 似乎不起作用)。

    这里使用的 $timeout 在广播更改之前会增加一点延迟。在某些情况下,如果在控制器中立即调用 showMessage()(在它完全构造之前),则消息不会出现,因此可以解决此问题。在较大的应用程序中可能还不够,但这相对较小。

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

    message-box.module.js

    /**
     * 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);
                }
            });
        }]);

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

    message-box.template.html

    <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>

    message-box.component.js没有改变)

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-06
      • 2016-11-05
      • 1970-01-01
      • 2013-08-27
      • 2015-11-08
      • 2019-07-31
      • 2014-01-25
      • 2018-06-09
      相关资源
      最近更新 更多