Why Is 'Replace' Property Deprecated in Angularjs Directives

Why is `replace` property deprecated in AngularJS directives?

UPDATE

One of the collaborators has said it won't be removed, but known bugs will not be fixed.
https://github.com/angular/angular.js/commit/eec6394a342fb92fba5270eee11c83f1d895e9fb#commitcomment-8124407

ORIGINAL

Here is the commit of this change:
https://github.com/angular/angular.js/commit/eec6394a342fb92fba5270eee11c83f1d895e9fb

The replace flag for defining directives that replace the element
that they are on will be removed in the next major angular version.
This feature has difficult semantics (e.g. how attributes are merged)
and leads to more problems compared to what it solves. Also, with
WebComponents it is normal to have custom elements in the DOM.

It sounds to me like its a combination of complexity vs benefit to maintain support.

And apparently one reason dev were using it because they prefered semantically correct markup to be injected , thus replacing the custom directive tag.


Read the comments lower down on that link and apparently many people want it to stay.

Why is `replace: true` Deprecated in AngularJS Directive

When I create a controller to the directive, and apply $scope.play = function() {}; nothing happens.

The problem that you are having is that you are using replace: true which is deprecated. Remove that and your directive's controller will see the click events.

angular.module("myApp").directive('logPlayer', function() {
return {
restrict: 'E',
//replace: true,
scope: {audio: '='},
controller: function($scope) {
$scope.play = function(index) {
console.log("play clicked "+index);
};
},
template: '<div ng-repeat="sample in audio">' +
'{{sample.title}}' +
'<button type="button" ng-click="play($index)">Play</button>' +
'<button type="button" ng-click="stop($index)">Stop</button>' +
'</div>'
};
});

The DEMO on JSFiddle.

From the Docs:

replace ([DEPRECATED!], will be removed in next major release - i.e. v2.0)

specify what the template should replace. Defaults to false.

  • true - the template will replace the directive's element.
  • false - the template will replace the contents of the directive's element.

-- AngularJS Comprehensive Directive API

From GitHub:

Caitp-- It's deprecated because there are known, very silly problems with replace: true, a number of which can't really be fixed in a reasonable fashion. If you're careful and avoid these problems, then more power to you, but for the benefit of new users, it's easier to just tell them "this will give you a headache, don't do it".

-- AngularJS Issue #7636

In this case the isolate scope of the directive is fighting the inherited scope of the ng-repeat directive. So either remove replace: true or remove the ng-repeat from the top element of the template.



Update

Note: replace: true is deprecated and not recommended to use, mainly due to the issues listed here. It has been completely removed in the new Angular.

Issues with replace: true

  • Attribute values are not merged
  • Directives are not deduplicated before compilation
  • transclude: element in the replace template root can have unexpected effects

For more information, see AngularJS $compile Service API Reference - Issues with replace:true.

How to substitute deprecated replace-property in Angular directives

That will give you same output as the directive with replace: true

angular.module('myModule')
.directive('myDirective', myDirectiveCtrl);

function myDirectiveCtrl() {
return {
'restrict': 'A',
'scope': false,
'template': 'content',
'link': function () {}
};
}

HTML

<div><span my-directive></span></div>

Replace true was causing a lot of troubles for developers when all the attributes, scope, had to be shifted to a new element, so the thing now is that you need to plan the DOM and directives different way so you won't use replace

and correct me if I'm wrong but I believe that with that you no longer need a template to contain single root element

previously template required single root element

<div>
<span></span>
<p></p>
</div>

now without single root element

<span></span>
<p></p>

AngularJS Directive property: Replace deprecated - Equivalent?

Docs appear to be outdated - replace for directives is not being removed.

Source

Why did Angular deprecate the old replace directive option?

When developers want to use your component, they have to look at your documentation to see what the name of the selector is. So what is the difference between you instructing the developers to use <app-my-component> vs <li app-my-component>? Note that component selectors support CSS selectors. In other words, you can ensure that your component only works with a <li> host element:

@Component({
selector: 'li[app-my-component]'
...
})

With a strict selector as shown, where you specify both the element and the attribute, you can prevent developers from using your component outside of its intended use.

For your example use case:

@Component({
selector: 'ul[app-platform-navigation-primary]'
...
})

and..

@Component({
selector: 'li[app-platform-navigation-secondary]'
...
})

The host element of a component does not have to be a <div>. It can be a <ul>, <li> or whatever else.

If you wish to abstract the fact that your component is using <ul> and <li> internally, then take a look at this SO answer. This answer demonstrates how you can wrap each child component inside <li>s within your parent component.

In summary, it is possible to achieve the same result as in AngularJs where you do not have extra elements but without the use of replace.

How to use the 'replace' feature for custom AngularJS directives?

replace:true is Deprecated

From the Docs:

replace ([DEPRECATED!], will be removed in next major release - i.e. v2.0)

specify what the template should replace. Defaults to false.

  • true - the template will replace the directive's element.
  • false - the template will replace the contents of the directive's element.

-- AngularJS Comprehensive Directive API

From GitHub:

Caitp-- It's deprecated because there are known, very silly problems with replace: true, a number of which can't really be fixed in a reasonable fashion. If you're careful and avoid these problems, then more power to you, but for the benefit of new users, it's easier to just tell them "this will give you a headache, don't do it".

-- AngularJS Issue #7636



Update

Note: replace: true is deprecated and not recommended to use, mainly due to the issues listed here. It has been completely removed in the new Angular.

Issues with replace: true

  • Attribute values are not merged
  • Directives are not deduplicated before compilation
  • transclude: element in the replace template root can have unexpected effects

For more information, see

  • AngularJS $compile Service API Reference - Issues with replace:true

How to use `replace` of directive definition?

You are getting confused with transclude: true, which would append the inner content.

replace: true means that the content of the directive template will replace the element that the directive is declared on, in this case the <div myd1> tag.

http://plnkr.co/edit/k9qSx15fhSZRMwgAIMP4?p=preview

For example without replace:true

<div myd1><span class="replaced" myd1="">directive template1</span></div>

and with replace:true

<span class="replaced" myd1="">directive template1</span>

As you can see in the latter example, the div tag is indeed replaced.

How to use `replace` of directive definition?

You are getting confused with transclude: true, which would append the inner content.

replace: true means that the content of the directive template will replace the element that the directive is declared on, in this case the <div myd1> tag.

http://plnkr.co/edit/k9qSx15fhSZRMwgAIMP4?p=preview

For example without replace:true

<div myd1><span class="replaced" myd1="">directive template1</span></div>

and with replace:true

<span class="replaced" myd1="">directive template1</span>

As you can see in the latter example, the div tag is indeed replaced.



Related Topics



Leave a reply



Submit