0

I want to use a directive to customize my code.

I have created a button to switch isCollapsedUpload flag defined in the controller as: @scope.isCollapsedUpload=false.

When the user presses the button, the isCollapsedUpload turns to true or vice versa and the icon changes.

From the controller:

$scope.switcher = function (booleanExpr, trueValue, falseValue) {
    return booleanExpr ? trueValue : falseValue;  
}

$scope.isCollapsedUpload = false;  

<button class="btn" ng-click="isCollapsedUpload = !isCollapsedUpload">                
    <span>Upload file</span>
    <i class="{{ switcher( isCollapsedUpload, 'icon-chevron-right', 'icon-chevron-down' )}}"></i>
</button>

I wrote this directive:

feederliteModule.directive('collapseExtend', function() {
return {
    restrict: 'E',
    scope: { isCollapsed:'@collapseTarget' },
    compile: function(element, attrs)
    { 
        var htmlText =
        '<button class="btn" ng-click="isCollapsed = !isCollapsed">'+       
        '       <span>'+attrs.label+'</span>'+  
        '       <i class="{{ switcher(isCollapsed, \'icon-chevron-right\', \'icon-chevron-down\' )}}"></i>'+  
        '</button>';

        element.replaceWith(htmlText);
    }
  }
});

And now I can use it like:

<collapse-extend 
              collapse-target="isCollapsedUpload"
              label="Upload file"                  
></collapse-extend>

It doesn't work. No icon changes. No errors,

isCollapsedUpload flag doesn't change. It changes only into directive

Did I miss something?

4

2 回答 2

2

类没有正确更改的原因是因为您没有正确链接模板。如果您使用内置功能,这很容易解决:

var feederliteModule = angular.module('feederliteModule', []);
feederliteModule.directive('collapseExtend', [function() {
  return {
    restrict: 'E',
    scope: { 
      isCollapsed:'=collapseTarget',
      label: '@'
    },
    template: '<button class="btn" ng-click="isCollapsed = !isCollapsed">'+       
                '<span>{{ label }}</span>'+  
                '<i ng-class="{ \'icon-chevron-right\': isCollapsed, \'icon-chevron-down\': !isCollapsed }"></i>'+  
              '</button>'
  }
}]);
feederliteModule.controller('test', ['$scope', function($scope) {
  $scope.isCollapsedUpload = false;
}]);

据我所知,通过替换父元素,您将删除与该对象相关联的隔离范围,而无需在按钮本身上创建新范围。

于 2013-05-17T14:23:15.400 回答
1

编辑: 查看fiddle使用多个按钮的完整工作


我建议使用 aservice而不是 acontroller来维护您的模型数据。当您的应用程序变得更加复杂时,这可以让您更好地分离关注点:

var feederliteModule = angular.module('feederliteModule', []);

feederliteModule.service('btnService', function(){
    this.isCollapsedUpload = false;
    this.isCollapsedSomething = false;
});

feederliteModule.controller('btnController', function($scope, btnService){
    $scope.isCollapsedUpload = btnService.isCollapsedUpload;
    $scope.isCollapsedSomething = btnService.isCollapsedSomething;
});

feederliteModule.directive('collapseExtend', function() {
    return {
        restrict: 'E',
        scope: {
            isCollapsed:'=collapseTarget',
            label:'@'
        },
        replace: true,
        link: function (scope, element, attrs){
            scope.switcher = function (booleanExpr, trueValue, falseValue) {
                return booleanExpr ? trueValue : falseValue;  
            };
            scope.toggleCollapse = function() {
               scope.isCollapsed = !scope.isCollapsed;
            }              
        },
        template: '<button class="btn" ng-click="toggleCollapse()">'+       
        '<span>{{label}}</span>'+
        '<i ng-class="switcher(isCollapsed, \'icon-chevron-right\', \'icon-chevron-down\')"></i>'+  
        '</button>'
    }
});

另外,请注意您必须使用 '=' 而不是 '@' 才能isCollapsed按预期工作。上面的答案也需要这个。

于 2013-05-17T17:10:43.683 回答