0
votes

In this plunk I have a directive that wraps a div. The div is shown when an ng-if condition is true (set with the click of a button).

The directive has a scope element css that is an object, where the object has an attribute width. Problem is that Angular complains when the directive is shown; see in the console the following error message when the button is clicked:

Expression '{ width: width}' in attribute 'css' used with directive 'modal' is non-assignable!

Note that this problem goes away when the $timeout in the directive is removed, but I cannot discard it.

Why does this happen and how to fix it (keeping the $timeout)?

HTML

<button ng-click="open()">Open modal</button>
<div modal ng-if="showModal" css="{ width: width}">
    <p>some text in modal</p>
</div>

Javascript

angular.module("app", [])

.controller('ctl', function($scope) {

  $scope.width = '200px';
  $scope.open = function(){
    $scope.showModal = true;
  };
})

.directive("modal", function($timeout) {

    var directive = {};

    directive.restrict = 'EA';

    directive.scope = { css: '=' };

    directive.templateUrl = "modal.html";

    directive.link = function (scope, element, attrs) {

            $timeout(function(){
                 scope.css.height = '100%';
            },100);

     };

     return directive;

});

Template

<style>
#modaldiv{
  border:2px solid red;
}
</style>
<div id="modaldiv" ng-style="{'width': css.width,'height': css.height}">
    Some content
</div>
1

1 Answers

1
votes

The error appears since you are not passing a scope variable to your css attribute.

You can fix this by creating a variable that holds your css in ctrl and pass this variable to the css attribute.

Controller

$scope.css = {width: $scope.width};

HTML

<div modal ng-if="showModal" css="css">
    <p>some text in modal</p>
</div>

Or alternatively create a local deep copy of css in the directive and manipulate the copy in your $timeout.

Directive

directive.link = function (scope, element, attrs) {
    scope.cssCopy = angular.copy(scope.css);
    $timeout(function(){
        scope.cssCopy.width = '100%';
    }, 100);
};

Template

<div id="modaldiv" ng-style="{'width': cssCopy.width,'height': cssCopy.height}">
    Some content
</div>