質問

In my parent controller:

//soemtimes view invoice has taxtotal defined
$scope.viewinvoice = {taxtotal:4}

//sometimes viewinvoice does not have taxtotal defined
$scope.viewinvoice = {}    

//sometimes it is defined but equal to 0
$scope.viewinvoice = {taxtotal:0}

In my parent view:

<div class="span6">
    <invoice invoice='viewinvoice'></invoice>
</div>

My directive:

.directive('invoice', [ function () {
  return {
    restrict: 'E',
    scope: {
      invoice:'='
    },
    replace: true,
    template: '<div>
        <input type="checkbox" ng-model="taxflag">
        <div> {{ calculate_grand_total() }} </div>
     </div>',
    link: function($scope, element, attrs) {
    }
  };
}]); 

In my directive I want to set $scope.taxflag true based on the property: $scope.invoice.taxtotal, the problem is if $scope.invoice.taxtotal is undefined I want to set the $scope.taxflag to false, and if the $scope.invoice.taxtotal is greater than 0 and is defined I want the $scope.taxflag set to true.

i.e.

if($scope.invoice.hasOwnProperty('taxtotal')){
    if($scope.invoice.taxtotal > 0 ) {
        $scope.taxflag = true;        
    } else {
        $scope.taxflag = false;
    }
} else {
    $scope.invoice.taxtotal = 0;
    $scope.taxflag = false;
}

I want this (above code) to act like 'initialization' code so whenever my 'viewinvoice' changes in the parent the $scope.taxflag and $scope.invoice.taxtotal will both be initially be set up correctly

I also want to trigger a change whenever the checkbox is checked:

i.e.

$scope.$watch('taxflag',function(newValue){
    if(newValue) {
        $scope.invoice.taxtotal = 5
    } else {
        $scope.invoice.taxtotal = 0;
    }
});

I am also using this $scope.invoice.taxtotal elsewhere in a function {{ calculate_grand_total() }} (in my directives view)

ie.

$scope.calculate_grand_total = function() {
    return $scope.invoice.taxtotal + 5;
}

but this is unable to render because $scope.invoice.taxtotal is not defined (at least initially) !!

Does this make sense? I have tried so many different combinations but I can't seem to get it working as I want it to.

役に立ちましたか?

解決

I've created this plunkr that tries to capture your question:

http://plnkr.co/edit/02QAC8m9xyF4pSyxnfOf

Basically, any code that depends on a value that can change should be in a watch. This means that your initialization code for setting taxflag belongs in a watch, so that it can update the tax flag if things change. This looks something like:

$scope.$watch('invoice.taxtotal', function(taxTotal) {
      if (!angular.isNumber(taxTotal)) {
        $scope.taxflag = false
        return;
      }
      if (taxTotal > 0) {
        $scope.taxflag = true;
      } else {
        $scope.taxflag = false;
      }
    });

Keep in mind watches are always executed the first time to initialize the values, so they essentially serve as both initialization code and update code.

As far as your calculate_grand_total function, if it is up to you to define what it should return if tax total or invoice are undefined. Simply check whether it is undefined and return the appropriate value, for example in my plunkr I return empty string:

$scope.calculate_grand_total = function() {
      if ($scope.invoice && angular.isNumber($scope.invoice.taxtotal)) {
        return $scope.invoice.taxtotal + 5;
      } else {
        return "";
      }
    }

I'm not sure if my plunkr works exactly like you want it or not, but it should get you started in the right direction. Or serve as a starting point for further clarification.

他のヒント

related:
if you only want to set first-run defaults you can use angular.merge inside your link:

link: function(scope, element, attr, ctrl) {
    // ....

    var settings_default = {
        setting1: true,
        setting2: {
            x: 0,
            y: 10
        },
    };

    //  order is important. last item overwrites previous
    scope.settings = angular.merge({}, settings_default, scope.settings);

    // ....
})
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top