指令,控制器和服务的双向绑定问题

时间:2016-02-11 12:09:49

标签: angularjs

这让我感到烦恼。 我有一个处理徽标面板的服务和一个用于在不同面板之间导航的功能。

当调用 getPanels 时,如果所有承诺都有,则会在服务上设置 currentPanel 索引长度已完成(请参阅 getPanels 方法中的 $ q.all ):

.service('ConfiguratorLogoService', ['$q', 'UploadService', 'LogoService', 'ArrayService', 'SvgService', function ($q, uploadService, logoService, arrayService, helper) {

    // Private function to build a file array
    var _buildFileArray = function (panels, files) {

        //--- Omitted for brevity ---//
    };

    // Create our service
    var service = {

        // Create our arrays
        panels: [],
        files: [],

        currentPanel: null,
        index: 0,
        length: 0,

        // Get our panels
        getPanels: function (container, garmentId) {

            // Create a deferred promise
            var deferred = $q.defer();

            // Create our arrays
            var panels = []
            files = [],
            promises = [];

            // If we have a container
            if (container) {

                // Get the containers children
                var children = container.children()

                // Loop through our panel's children
                for (var i = 0; i < children.length; i++) {

                    // Get the current child
                    var child = angular.element(children[i]),
                        childId = child.attr('id'),
                        childTitle = helper.extractText(childId, ':', 1);

                    // Create our item
                    var panel = {
                        id: childId,
                        title: childTitle
                    };

                    // Try to get our item
                    promises.push(logoService.get(garmentId, panel.id).then(function (response) {

                        // If we have any data
                        if (response) {

                            // Add the file to our array
                            files.push(response);
                        }
                    }));

                    // Add our child to the array
                    panels.push(panel);
                }
            }

            // After all the promises have been handled
            $q.all(promises).then(function () {

                // Get our files
                service.files = _buildFileArray(panels, files);
                service.panels = panels;
                service.currentPanel = panels[0];
                service.length = panels.length;

                // Resolve our promise
                deferred.resolve({
                    files: service.files,
                    panels: panels
                });
            });

            // Return our promise
            return deferred.promise;
        },

        // Get our next panel
        navigateNext: function () {

            // Create a deferred promise
            var deferred = $q.defer();

            // Get the next index or reset if we reached the end of our list
            service.index = service.index === (service.length - 1) ? 0 : service.index += 1;

            // Set our active panel
            service.currentPanel = service.panels[service.index];

            console.log(service.index);

            // Resolve our promise
            deferred.resolve();

            // Return our promise
            return deferred.promise;
        },

        // Get our previous panel
        navigatePrevious: function () {

            // Get the previous index or set to the end of our list
            service.index = service.index === 0 ? service.length - 1 : service.index -= 1;

            // Set our active panel
            service.currentPanel = service.panels[service.index];
        },

        // Removes the file from azure
        remove: function (index) {


            //--- Omitted for brevity ---//

        }
    };

    // Return our service
    return service;
}])

这很好,它工作,并选择第一个面板。 所以,我有一个控制器,它附加到一个指令。控制器如下所示:

.controller('ConfiguratorLogosDirectiveController', ['ConfiguratorLogoService', 'RowService', function (service, rowService) {
    var self = this;

    // Set our current panel
    self.currentPanel = service.currentPanel;
    self.index = service.index;
    self.length = service.length;

    // Initialization
    self.init = function (container, garmentId) {

        // Get our panels
        return service.getPanels(container, garmentId).then(function (response) {

            self.panels = response.panels;
            self.files = response.files;

            // If we have any panels
            if (self.panels.length) {

                // Set our current panel
                self.currentPanel = service.currentPanel;
                self.index = service.index;
                self.length = service.length;
            }

            // Return our response
            return response;
        })
    };

    // Map our service functions
    self.upload = service.upload;
    self.next = service.navigateNext;
    self.previous = service.navigatePrevious;
    self.remove = service.remove;
}])

正如你所看到的,当我拿到我的面板时,我在控制器本身上设置 currentPanel 索引长度,我没有#39;我想我必须这样做,因为在调用控制器时,它已经有了对服务值的引用。我认为2路绑定会发挥作用,当服务值更新时,控制器也会更新。

无论如何,我在 getPanels 方法成功完成后更新了值。在我的指示中我有这个:

// Invoke on controller load
controller.init(container, scope.garmentId).then(function (response) {

    // Map our properties
    scope.panels = controller.panels;
    scope.files = controller.files;
    scope.currentPanel = controller.currentPanel;
    scope.index = controller.index;
    scope.length = controller.length;
});

再次正常工作。在我的模板中,我可以看到第一个面板,它看起来很好。 那么,下一步就是我的导航功能。我从 next 开始,我已经为测试目的进行了修改,因此我可以在服务导航功能中输出 controller.index 以及console.log。 指令函数如下所示:

scope.next = function () {
    controller.next().then(function () {
        console.log(controller.index);
    });
};

当调用此方法时,我可以在我的控制台中看到该服务将索引增加1但控制器仍然显示0,这意味着双向绑定不起作用。 我即将在控制器中更新我的方法,将 currentPanel 和索引推送到控制器,但在此之前,我想我会先问这里。

那么,有没有人知道为什么我的2路绑定不起作用?

所以我目前的解决方法有效,但我不喜欢它。 在我的指示中,我做到了这一点:

scope.next = function () {
    controller.next().then(function () {

        console.log(controller.index);
        scope.currentPanel = controller.currentPanel;
        scope.index = controller.index;
        scope.length = controller.length;
    });
}

在指令控制器中我做到了:

self.next = function () {

    // Try to navigate forward
    return service.navigateNext().then(function () {

        // Set our current panel
        self.currentPanel = service.currentPanel;
        self.index = service.index;
        self.length = service.length;

        console.log(self.index);
    });
}

在我的服务中,它看起来和以前一样:

// Get our next panel
navigateNext: function () {

    // Create a deferred promise
    var deferred = $q.defer();

    // Get the next index or reset if we reached the end of our list
    service.index = service.index === (service.length - 1) ? 0 : service.index += 1;

    // Set our active panel
    service.currentPanel = service.panels[service.index];

    console.log(service.index);

    // Resolve our promise
    deferred.resolve();

    // Return our promise
    return deferred.promise;
},

这样可行,但肯定不是它的工作方式。

1 个答案:

答案 0 :(得分:0)

我已经弄明白了thanks to this article

我只需要在我的指令中创建一个对象并将值绑定到该指针。 这样做可以解决问题。