Angular中的滑动菜单通过$ provider

时间:2017-01-18 19:47:07

标签: javascript angularjs

这是我遇到问题的二合一。

问题

我有一个滑块菜单,我在移动应用中创建了导航功能。菜单生成得很好,它被编译并显示出来。我可以轻弹前几个链接,然后按下后退,它将关闭,但是当我点击最后一个链接时,它根本不会关闭。它甚至没有回应。我必须重新启动应用程序,我打开检查器,它没有显示任何错误。所以我假设模板搞砸了,模板中没有错。提供商的源代码看起来似乎没问题,也许有订购问题?

其次。我将menuInstance变量传递给需要它的所有区域,并且我试图设置一个自闭函数,但这也没有被识别。因此,所有这些可能共同构成一个非常酷的功能,但唉,没有什么工作正常,除了打开。

那么我如何让它识别它的实例,这样我就可以从它自己的控制器中关闭命令窗口,其次为什么在推送最后一个链接后它不能识别它自己。

这是菜单的小提琴,以便您可以看到行为:

https://jsfiddle.net/Mr_Pikachu/4brubsst/49/

当前源代码(严格模式)

/**
* Angular Slider Menu Widget
*/

// generate initial module and child modules
angular.module('sw.js.widget.slidermenu', ['ngAnimate', 'ngRoute']);
angular.module('sw.js.widget.slidermenu').directive('menuOverlayBackdrop', MenuOverlayBackdropDirective);
angular.module('sw.js.widget.slidermenu').directive('menuSlideCall', MenuSlideCallDirective);
angular.module('sw.js.widget.slidermenu').factory('$sliderMenuStack', SliderMenuStackFactory);
angular.module('sw.js.widget.slidermenu').provider('$sliderMenu', SliderMenuProvider);


// inject dependecies for each module as needed
MenuOverlayBackdropDirective.$inject = ['$sliderMenuStack'];
SliderMenuStackFactory.$inject = ['$document', '$compile', '$animate', '$rootScope'];

// create module functions
function MenuOverlayBackdropDirective($sliderMenuStack){
    return {
        compile : function(element, attrs){
            element.addClass('widget-show');
            return linkFn;
        }
    };
    function linkFn(scope, element, attr){
        scope.$on($sliderMenuStack.MENU_CLOSING, function(){
            var instance = $sliderMenuStack.get();
            instance.close(instance);
        });
    }
}


function MenuSlideCallDirective(){
    return {
        templateUrl : function(elem, attrs){
            return attrs.templateUrl;
        },
        compile : function(element, attrs){
            element.addClass('slide-left');
        }
    };
}

function SliderMenuStackFactory($document,  $compile, $animate, $rootScope){
   $menuStack = {
        'MENU_CLOSING' : 'closing',
        'MENU_CLOSED' : 'closed',
        'instance' : null,
        'menu' : null,
        'open': function(menuInstance, menu) {
            //console.log(menuInstance, menu);
            //menuOpts.scope.main = menuOpts.menu.main;
            var appendToEl = menu.appendTo;
            var backdropEl = angular.element("<div class='widget-backdrop' menu-overlay-backdrop></div>");
            var backdropScope = $rootScope.$new();
            backdropEl.bind('click', function(){
                backdropScope.$broadcast($menuStack.MENU_CLOSING);
            });
            var menuEl = angular.element("<div class='slider-menu-container' menu-slide-call template-url="+menu.template+"></div>");

            menuInstance.backdropEl = backdropEl;
            menuInstance.menuEl = menuEl;
            menuInstance.scope = menu.scope;
            menu.scope.close = menuInstance.close;
            $menuStack.set(menuInstance);

            $compile(menuEl)(menu.scope);
            $compile(backdropEl)(backdropScope); 
            $animate.enter(backdropEl, appendToEl).then(function(){
                $animate.enter(menuEl, appendToEl);
            });

        },
        'close' : function(menuInstance){
            menuInstance.scope.$apply(function(){
                $animate.leave(menuInstance.menuEl).then(function(){
                    menuInstance.backdropEl.remove();
                    menuInstance = null;
                    $menuStack.set(menuInstance);
                });
            });
        },
        'set' : function(instance){
            $menuStack.instance = instance;
        },
        'get' : function(){
            return $menuStack.instance;
        },
        'remove' : function(){
            $menuStack.instance = null;
        }
    };

    return $menuStack;
}

function SliderMenuProvider(){
   $menuProvider = {};
    $menuProvider.options = {
        background : true
    };
    $menuProvider.$get = ['$sliderMenuStack', '$q', '$rootScope', '$controller', '$document', function($sliderMenuStack, $q, $rootScope, $controller, $document){
        return {
            open : function(menuOptions){
                var menu = {};
                // preparing a new instance of the menu to be injected
                var menuInstance = {
                    close : function(){
                        $sliderMenuStack.close(menuInstance);
                    }
                };
                menuOptions = angular.extend({}, $menuProvider.options, menuOptions);
                var providedScope = menuOptions.scope || $rootScope;
                menuScope = providedScope.$new();
               // menuScope.$close = menuInstance.close();
                menu.scope = menuScope;
                menu.appendTo = $document.find('body').eq(0);
                menu.template = menuOptions.templateUrl;

                // generate the controller and then create an instance of the controller to be used
                var ctrlInstantiate = $controller(menuOptions.controller, {$scope : menuScope}).constructor;
                $sliderMenuStack.open(menuInstance, menu);
            }
        };
    }];
    return $menuProvider;
}

以下是我要加载的页面模板:

<main class='container-fluid'>
    <div class='row'>
        <section class='col-xs-12'>
            <ul class='list-group headed-list-group'>
                <ng-repeat ng-repeat='(k, track) in tracks'>
                    <li class='list-group-item list-group-heading'>{{k}}</li>
                    <li class='list-group-item title clearfix' ng-repeat="t in track">
                        <div class='col-xs-2'></div>
                        <div class='col-xs-8'>
                            <table class='track-table'>
                                <tr><td class='track-title'>{{t.name}}</td></tr>
                                <tr><td class='track-cat'>{{t.subtitle}}</td></tr>
                                <tr><td class='track-stats'></td></tr>
                            </table>
                        </div>
                        <div class='col-xs-2'>
                            <p class='text-center form-control-static text-right'>
                                <!--<i class='fa fa-ellipsis-v' downloads-drawer></i>-->
                            </p>
                        </div>
                    </li>
                </ng-repeat>
            </ul>
        </section>
    </div>
</main>

希望这指向了我想要去的方向。如果您需要更多源代码或有关错误集的信息,请快速评论,我会尽我所能。我想尽快解决这个问题。它困扰了我好几天,我想很快继续下一期。提前谢谢!

1 个答案:

答案 0 :(得分:0)

因此,经过几个小时的阅读和一些代码实验后,我终于得到了工作解决方案!

您必须通过locals选项将menuInstance注入控制器,然后相应地更新代码。我有下面的例子和工作小提琴。

<强>拨弄

https://jsfiddle.net/Mr_Pikachu/4brubsst/51/

<强>解

$ sliderMenu

<强>从

var ctrlInstantiate = $controller(menuOptions.controller, {$scope : menuScope).constructor;

var ctrlInstantiate = $controller(menuOptions.controller, {$scope : menuScope, $menuInstance : menuInstance}).constructor;

$ sliderMenuStack

<强>从

'close' : function(menuInstance){
     menuInstance.scope.$apply(function(){
         $animate.leave(menuInstance.menuEl).then(function(){
             menuInstance.backdropEl.remove();
             menuInstance = null;
             $menuStack.set(menuInstance);
         });
     });
 }

'close' : function(menuInstance){
    $animate.leave(menuInstance.menuEl).then(function(){
         menuInstance.backdropEl.remove();
         menuInstance = null;
         $menuStack.set(menuInstance);
    });
 }

menuOverlayBackdrop

将整个return语句更新为以下内容:

return {
    compile : function(element, attrs){
        element.addClass('widget-show');
        return linkFn;
    }
};
function linkFn(scope, element, attr){
    scope.$on($sliderMenuStack.MENU_CLOSING, function(){
        var instance = $sliderMenuStack.get();
        instance.close(instance);
        instance.scope.$apply(function(){
            $animate.leave(instance.menuEl).then(function(){
                instance.backdropEl.remove();
                //menuInstance = null;
            });
        });
    });
}

然后最后确保在调用提供程序时,在控制器函数中包含$menuInstance注入变量,以确保一切正常。