在 angularjs 中创建一个容器指令 [英] Create a container directive in angularjs

查看:27
本文介绍了在 angularjs 中创建一个容器指令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我正在尝试创建一个指令,该指令将在列中布局一组项目.在 plunker 中,我有一个极其简化的版本,它只使用一个 ul,但这并不重要.我希望指令像 .

一样被调用

<tab name="{{ item }}"></tab></my-column-layout>

我想使用内部 html(此处的选项卡)作为集合中每个项目的模板.我试着只是在 my-column-layout 模板中有一个 ng-repeat 像

template : '
  • </li></ul>

有效,但它无法访问包含的控制器范围,因此我无法在选项卡上有任何单击事件并让它调用控制器中的函数.所以我认为我使用 transclude 朝着正确的方向前进,但不确定.此外,当我尝试向名称集合中添加一些其他名称时,这不会显示在我的指令的集合中.我的 scope.$watch('collection' ...) 从未被调用过.

http://plnkr.co/edit/4vyZDAhBcbULEd3uIznh?p=preview

希望有人能帮忙

解决方案

我做了一些我认为类似的事情.如果我以某种方式错过了重点,请告诉我.我有一个指令,它根据远程数据执行嵌入的 ng-repeat.这是它的工作原理.

更新

问题在于页面标记中的模板.但是,如果您希望 ng-repeat 模板存在于同一页面标记上,您可以这样做:

不完全一样的东西,但它给你同样的效果——模板与指令在同一页面上——只是没有嵌套.

更新结束

我在父作用域和子作用域中有相同的数组:即 $scope.items.因为它是一个引用类型,通过原型继承,两个作用域都引用同一个对象.在不更新属性的位置,我像这样初始化它 $scope.items = $scope.items ||[]; -- 即如果该属性尚未初始化,则对其进行初始化,否则保留.

directive('navbar', ['$location', '$http', function ($location, $http) {返回 {限制:'E',转置:真实,范围:{标题:'@'},控制器:'NavbarCtrl',templateUrl: 'navbar.html',替换:真的,链接:函数($scope,$element,$attrs,navbarCtrl){$scope.items = [];$scope.heading = $scope.heading ||$attrs.heading;$http.get(itemsUrl).success(function(data) {$scope.items = ... 异步获取数据 ... ;navbarCtrl.selectByUrl($location.absUrl());});$scope.$watch('$location.absUrl()', function (locationPath) {navbarCtrl.selectByUrl(locationPath)});}}}])

指令的 $watch 调用一个控制器函数,该函数可以通过它的闭包访问控制器 $scope.

function NavbarCtrl($scope, $timeout, $http, $location, $attrs) {$scope.items = $scope.items ||[];this.select = $scope.select = function (item) {angular.forEach($scope.items, function (item) {item.selected = false;});item.selected = true;};this.selectByUrl = 函数(网址){angular.forEach($scope.items, function (item) {if ('http://' + item.link === url) {$scope.select(item);}});};}

然后,在我嵌入的模板中,我有:

  • <a href="/{{item.link}}">{{item.title}}</a>
  • 在页面标记中,我是这样使用的:

    <导航栏标题="导航栏标题"/>

    So I'm trying to create a directive that will layout a collection of items in columns. In the plunker I have a extremely simplified version which only uses a single ul, but that is not important. I want the directive to be called like .

    <my-column-layout collection="names">
        <tab name="{{ item }}"></tab>
    </my-column-layout>
    

    I want to use the inner html (the tab here) as a template for each item in the collection. I tried to just have a ng-repeat in the my-column-layout template like

    template : '<ul><li ng-repeat="item in collection" ng-transclude></li></ul>
    

    which worked but it didnt have access to the containing controllers scope, so I couldn't have any click events on the tab and have it call an function in the controller. So i think I am heading the right direction with using transclude but not sure. Also when I try to add some other name to the collection of names, then this doesnt show up in the collection in my directive. My scope.$watch('collection' ...) is never called.

    http://plnkr.co/edit/4vyZDAhBcbULEd3uIznh?p=preview

    Hope someone can help

    解决方案

    I do something that I think is similar. Let me know if I've somehow missed the point. I have a directive that does a transcluded ng-repeat based on remote data. Here's how it works.

    Update

    It's the template in the page markup that's the issue. However, if you want the ng-repeat template to exist on the same page markup, you can do this:

    <script type="text/ng-template" id="navbar.html">
        <li ng-repeat="item in items" ng-class="{active: item.selected}">
            <a href="/{{item.link}}">{{item.title}}</a>
        </li>
    </script>
    

    Not exactly the same thing, but it get's you the same effect - template on the same page as the directive - just not nested with it.

    Update End

    I have the same array in the parent and the child scopes: i.e. $scope.items. Because it's a reference type, through prototypical inheritance, both scopes reference the same object. In the location that doesn't update the property, I initialize it like this $scope.items = $scope.items || []; -- i.e. if the property hasn't been initialized, initialize it, otherwise keep it.

    directive('navbar', ['$location', '$http',  function ($location, $http) {
        return {
            restrict: 'E',
            transclude: true,
            scope: { heading: '@'},
            controller: 'NavbarCtrl',
            templateUrl: 'navbar.html',
            replace: true,
            link: function ($scope, $element, $attrs, navbarCtrl) {
    
                $scope.items = [];
                $scope.heading = $scope.heading || $attrs.heading;
    
                $http.get(itemsUrl).success(function(data) {
                    $scope.items = ... async get of data ... ;
                    navbarCtrl.selectByUrl($location.absUrl());
                });
    
                $scope.$watch('$location.absUrl()', function (locationPath) {
                    navbarCtrl.selectByUrl(locationPath)
                });
            }
        }
    }])
    

    The directive's $watch calls a controller function, and that function has access to the controller $scope through its closure.

    function NavbarCtrl($scope, $timeout, $http, $location, $attrs) {
        $scope.items = $scope.items || [];
    
        this.select = $scope.select = function (item) {
            angular.forEach($scope.items, function (item) {
                item.selected = false;
            });
            item.selected = true;
        };
    
        this.selectByUrl = function (url) {
            angular.forEach($scope.items, function (item) {
                if ('http://' + item.link === url) {
                    $scope.select(item);
                }
            });
        };
    }
    

    Then, in my template, which I transclude, I have:

    <li ng-repeat="item in items" ng-class="{active: item.selected}">
        <a href="/{{item.link}}">{{item.title}}</a>
    </li>
    

    In the page markup, I use it like this:

    <div ng-controller="NavbarCtrl">
        <navbar heading="Navbar Heading"/>
    </div>
    

    这篇关于在 angularjs 中创建一个容器指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆