AngularJS - 从指令更改父范围?

时间:2013-12-23 22:55:24

标签: javascript angularjs

我正在构建我的第一个Angular应用程序,但是在使用某些东西时遇到了一些麻烦。我有一个视频容器将被隐藏,直到$ scope.video.show = true;我在点击链接时尝试设置此值。我试图在指令中实现这一点。任何帮助将不胜感激。

HTML:

<div ng-controller="AppCtrl">
    <div ng-cloak 
         ng-class="{'show':video.show, 'hide':!video.show}">
                  // youtube iframe content, for example
    </div>

    <div>
        <ul>
            <li>
                <h3>Video Headline 1</h3>
                <button type="button" 
                    video-show 
                    data-video-id="jR4lLJu_-wE">PLAY NOW&nbsp;&rang;</button>
            </li>
            <li>
                <h3>Video Headline 2</h3>
                <button type="button" 
                    video-show 
                    data-video-id="sd0f9as8df7">PLAY NOW&nbsp;&rang;</button>
            </li>
        </ul>
    </div>
</div>

的javascript:

var thisViewModel = angular.module("savings-video", [])
.controller('SavingsVideoController', function($scope) {

    $scope.video = {
        show : false,
        videoId : ""
    };
};

thisViewModel.directive("videoShow", function(){
    return{
        restrict: 'A',
        link: function(scope , element){

            element.bind("click", function(e){

                var $this = angular.element(element);
                $this.closest('li').siblings().addClass('hide');   // hide the other one
                $this.closest('li').removeClass('hide');           // keep me open


                scope.video.show = true;  // doesn't work.  
                     // what is the best way to do this?

            });
        }
    }
});

3 个答案:

答案 0 :(得分:1)

我看到了一些你可以改进的事情。

  1. 结帐ngShow / ngHidengIf;他们会比试图从头开始更容易给你切换能力。
  2. Think in angular。不要试图使用逻辑来自己修改DOM,而只需使用angular指令设置规则,让框架为您完成剩下的工作。
  3. 例如,看起来这更像是你想要的。

    <div ng-controller="AppCtrl">
        <div ng-cloak ng-show='video.show">
                  // youtube iframe content, for example
        </div>
    
        <div>
            <ul ng-switch="video.videoId">
                <my-video my-video-id="jR4ABCD" my-headline="Video Headline 1" ng-switch-when="myVideoId" my-video-manager="video" />
                <my-video my-video-id="al1jd89" my-headline="Video Headline 2" ng-switch-when="myVideoId" my-video-manager="video"/>
            </ul>
        </div>
    </div>
    

    我更改的内容是使用ngShow有条件地展示您的iframe,并使用ngSwitch来控制显示哪个视频(显示的视频基于$ scope的video.videoId)。然后,我将您的<li>转换为名为my-video的指令,最终看起来像这样

    thisViewModel.directive("my-video", function(){
        return{
            restrict: 'E',
            replace: true,
            scope: {
               myVideoId = "=",
               myHeadline = "=",
               myVideoManager = "="
            },
            template = '<li><h3>{{myHeadline}}</h3><button type="button" ng-click="play()">PLAY NOW&nbsp;&rang;</button></li>',
            link: function(scope , element){
                scope.play = function(){
                     myVideoManager.show = true;
                    /*whatever you want here, using scope.myVideoId*/
                }
            }
        }
    });
    

    此指令完全与您的旧HTML相同,但将其引入角度框架,以便您可以访问您正在寻找的属性。通过使用原始角度指令,我消除了对任何手动UI逻辑的需求;我根本不需要访问element,我的HTML和JavaScript都更清晰。这里肯定有改进的余地,但我会说这更接近正确的轨道。

    需要练习才能更熟悉,但遵循上述SO链接中的指南会有所帮助。

    修改

    抱歉,我想第一次错过了一项要求。如果您希望在未选择任何视频时显示这两个视频,请不要使用ng-switch;只需设置一些手册ng-show s。

        <div>
            <ul>
                <my-video my-video-id="jR4ABCD" my-headline="Video Headline 1" ng-show="myVideoId == video.videoId" my-video-manager="video" />
                <my-video my-video-id="al1jd89" my-headline="Video Headline 2" ng-show="myVideoId == video.videoId" my-video-manager="video"/>
            </ul>
        </div>
    

    因为ng-switch实际上只是ng-show的快捷方式,所以它相同;刚刚将逻辑移入ng-show属性。

    此外,如果您有一系列视频,请结帐ng-repeat;它会让您自动多次重复视频标记,而不是手动重复。

    <ul>
       <my-video ng-repeat='aVideo in myVideoArray' my-video-id='aVideo.videoId' my-headline...(and so on)>
    </ul>
    

答案 1 :(得分:0)

你的控制器名称不匹配。尝试将AppCtrl更改为SavingsVideoController

答案 2 :(得分:0)

您只需要一个非常简单的解决方案。

HTML

<div ng-controller="AppCtrl">
    <div ng-cloak ng-show="view.show">
        <!-- Use ng-show is more convenient -->
    </div>

    <div>
        <ul>
            <li>
                <h3>Video Headline 1</h3>
                <button type="button" 
                    ng-click="view.show = true"
                    data-video-id="jR4lLJu_-wE">PLAY NOW&nbsp;&rang;</button>
                    <!-- You don't need an extra directive to change view.show -->
            </li>
            <li>
                <h3>Video Headline 2</h3>
                <button type="button" 
                    ng-click="view.show = true"
                    data-video-id="sd0f9as8df7">PLAY NOW&nbsp;&rang;</button>
            </li>
        </ul>
    </div>
</div>

JS

var thisViewModel = angular.module("savings-video", [])
.controller('SavingsVideoController', function($scope) {

    $scope.video = {
        show : false,
        videoId : ""
    };
};

// No need to create another directive