0

I have a layout with multiple elements which are able to gain target. I need to target only one element at the time. Is it possible to define a function on the $scope that receives an object from the model (for example a line item belonging to an invoice) and tell Angular to add a css class wherever the view of this model is?

If I use the ng-class directive, it would force me to add ng-class to all "targetable" elements in the html and each element should know if it is the current target or not. I don't want to add an isTarget() function to each possible element because it will dirty the model.

Example: This is the html:

<p>{{document.shipFrom}}</p>
<p>{{document.shipTo}}</p>
<ul>
    <li ng-repeat="item in document.items">{{item.description}}</li>
</ul>

And this is the controller:

angular.module('myApp').controller('DocumentCtrl', function($scope){
    $scope.document = {
        shipFrom: 'Origin',
        shipTo: 'Destination',
        items: [
            {description:'item1'},
            {description:'item2'}
        ]
    };
})

Is there a way to define $scope.setTarget($scope.document.items[0]) so that it adds a class "on-target" to the element? Note that all the document properties (the items and the shipFrom/To) can gain target.

Edit: Solved

I found a way to get a model's attribute value in my directive's linking function. If I use the $parse service then I can evaluate the model's property attached to the directive simply by instantiating a getter function:

link: function postLink ($scope, $iElement, $iAttrs) {
    var valueGetter = $parse($iAttrs.ngModel);

    //Then, I can subscribe the directive to a custom event:
    $scope.$on('set.target', function (event, elem) {
        $iElement.removeClass('on-target alert-info');
        //Now it gets the actual value of the model related to the directive
        var value = valueGetter($scope);
        //If both the model and the event's value are the same, then focus the element.
        if (value == elem) {
            $iElement.addClass('on-target alert-info');
            $scope.setTarget(valueName, elem);
            $scope.$apply();
    }
    return;
    });
}//end link function

When I need something to gain target from the controller, then I just do $scope.$broadcast('set.target', $scope.document.shipFrom)

4

2 回答 2

0

HTML部分:

<p>{{document.shipFrom}}</p>
<p>{{document.shipTo}}</p>
<ul>
  <li ng-repeat="item in document.items" ng-click="setTarget(item.description)" ng-class="{'active' : selectedTarget == item.description}">{{item.description}}</li>
</ul>   

控制器:

$scope.document = {
    shipFrom: 'Origin',
    shipTo: 'Destination',
    items: [
        {description:'item1'},
        {description:'item2'}
    ]
};

$scope.selectedTarget = '';  

$scope.setTarget = function(data) {
  $scope.selectedTarget = data;  
};

演示

于 2013-09-18T19:34:00.107 回答
0

如果您不想为每个可能的项目添加 isTarget() 函数,则可以在文档中添加 isTarget 方法。

isTarget: function(item){
  return this.target === item;
}

并将html更改为

<li ng-repeat="item in document.items" ng-class="{'on-target': document.isTarget(item)}">{{item.description}}</li>
于 2013-09-18T19:35:06.880 回答