Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Flip the $compileProvider.preAssignBindingsEnabled flag to false by default #15350

Closed
mgol opened this issue Nov 2, 2016 · 0 comments
Closed

Comments

@mgol
Copy link
Member

mgol commented Nov 2, 2016

Note: for support questions, please use one of these channels: https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#question. This repository's issues are reserved for feature requests and bug reports.

Do you want to request a feature or report a bug?
A breaking change request.

What is the current behavior?
$compileProvider.preAssignBindingsEnabled is set to true by default. This means bindings are pre-assigned in component constructors.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://plnkr.co or similar (template: http://plnkr.co/edit/tpl:yBpEi4).

What is the expected behavior?
$compileProvider.preAssignBindingsEnabled should be false by default.

What is the motivation / use case for changing the behavior?
The true value of the flag causes bindings to be pre-assigned in component constructors which introduces unneeded (now that we have the $onInit lifecycle hook) complexity (we can't use regular new MyConstructor() way of creating controllers) and doesn't work with ES6 classes.

Which versions of Angular, and which browser / OS are affected by this issue? Did this work in previous versions of Angular? Please also test with the latest stable and snapshot (https://code.angularjs.org/snapshot/) versions.
All.

Other information (e.g. stacktraces, related issues, suggestions how to fix)

@mgol mgol added this to the 1.6.0-rc.1 milestone Nov 2, 2016
@mgol mgol self-assigned this Nov 2, 2016
mgol added a commit to mgol/angular.js that referenced this issue Nov 2, 2016
Fixes angular#15350

BREAKING CHANGE: Previously, $compileProvider.preAssignBindingsEnabled was
set to true by default. This means bindings were pre-assigned in component
constructors. In Angular 1.5+ the place to put the initialization logic
relying on bindings being present is the controller $onInit method.

To migrate follow the example below:

Before:

```js
angular.module('myApp', [])
  .component('myComponent', {
    controller: 'MyController',
    template: '<div>{{ $ctrl.a }} + {{ $ctrl.b }} = {{ $ctrl.sum }}</div>',
    bindings: {
      a: '<',
      b: '<'
    }
  })
  .controller('MyController', function() {
    this.sum = this.a + this.b;
  });
```

After:
```js
angular.module('myApp', [])
  .component('myComponent', {
    controller: 'MyController',
    template: '<div>{{ $ctrl.a }} + {{ $ctrl.b }} = {{ $ctrl.sum }}</div>',
    bindings: {
      a: '<',
      b: '<'
    }
  })
  .controller('MyController', function() {
    this.$onInit = function () {
      this.sum = this.a + this.b;
    };
  });
```

If you need to support both Angular 1.4 and 1.6, e.g. you're writing a library,
you need to check for Angular version and apply proper logic. Follow the
example below:

Before:
```js
angular.module('myApp', [])
  .directive('myDirective', function() {
    return {
      controller: 'MyController',
      template: '<div>{{ $ctrl.a }} + {{ $ctrl.b }} = {{ $ctrl.sum }}</div>',
      scope: {
        a: '=',
        b: '='
      },
      bindToController: true,
      controllerAs: '$ctrl'
    };
  })
  .controller('MyController', function($scope) {
    this.sum = this.a + this.b;
  });
```

After:
```js
angular.module('myApp', [])
  .config(function($compileProvider) {
    $compileProvider.preAssignBindingsEnabled(false);
  })
  .directive('myDirective', function() {
    return {
      controller: 'MyController',
      template: '<div>{{ $ctrl.a }} + {{ $ctrl.b }} = {{ $ctrl.sum }}</div>',
      scope: {
        a: '=',
        b: '='
      },
      bindToController: true,
      controllerAs: '$ctrl'
    };
  })
  .controller('MyController', function($scope) {
    this.$onInit = function() {
      this.sum = this.a + this.b;
    };
    if (angular.version.major === 1 && angular.version.minor <= 4) {
      this.$onInit();
    }
  });
```
mgol added a commit to mgol/angular.js that referenced this issue Nov 3, 2016
Fixes angular#15350

BREAKING CHANGE: Previously, $compileProvider.preAssignBindingsEnabled was
set to true by default. This means bindings were pre-assigned in component
constructors. In Angular 1.5+ the place to put the initialization logic
relying on bindings being present is the controller $onInit method.

To migrate follow the example below:

Before:

```js
angular.module('myApp', [])
  .component('myComponent', {
    controller: 'MyController',
    template: '<div>{{ $ctrl.a }} + {{ $ctrl.b }} = {{ $ctrl.sum }}</div>',
    bindings: {
      a: '<',
      b: '<'
    }
  })
  .controller('MyController', function() {
    this.sum = this.a + this.b;
  });
```

After:
```js
angular.module('myApp', [])
  .component('myComponent', {
    controller: 'MyController',
    template: '<div>{{ $ctrl.a }} + {{ $ctrl.b }} = {{ $ctrl.sum }}</div>',
    bindings: {
      a: '<',
      b: '<'
    }
  })
  .controller('MyController', function() {
    this.$onInit = function () {
      this.sum = this.a + this.b;
    };
  });
```

If you need to support both Angular 1.4 and 1.6, e.g. you're writing a library,
you need to check for Angular version and apply proper logic. Follow the
example below:

Before:
```js
angular.module('myApp', [])
  .directive('myDirective', function() {
    return {
      controller: 'MyController',
      template: '<div>{{ $ctrl.a }} + {{ $ctrl.b }} = {{ $ctrl.sum }}</div>',
      scope: {
        a: '=',
        b: '='
      },
      bindToController: true,
      controllerAs: '$ctrl'
    };
  })
  .controller('MyController', function($scope) {
    this.sum = this.a + this.b;
  });
```

After:
```js
angular.module('myApp', [])
  .directive('myDirective', function() {
    return {
      controller: 'MyController',
      template: '<div>{{ $ctrl.a }} + {{ $ctrl.b }} = {{ $ctrl.sum }}</div>',
      scope: {
        a: '=',
        b: '='
      },
      bindToController: true,
      controllerAs: '$ctrl'
    };
  })
  .controller('MyController', function($scope) {
    this.$onInit = function() {
      this.sum = this.a + this.b;
    };
    if (angular.version.major === 1 && angular.version.minor <= 4) {
      this.$onInit();
    }
  });
```
mgol added a commit to mgol/angular.js that referenced this issue Nov 3, 2016
Fixes angular#15350

BREAKING CHANGE: Previously, $compileProvider.preAssignBindingsEnabled was
set to true by default. This means bindings were pre-assigned in component
constructors. In Angular 1.5+ the place to put the initialization logic
relying on bindings being present is the controller $onInit method.

To migrate follow the example below:

Before:

```js
angular.module('myApp', [])
  .component('myComponent', {
    bindings: {value: '<'},
    controller: function() {
      this.doubleValue = this.value * 2;
    }
  });
```

After:
```js
angular.module('myApp', [])
  .component('myComponent', {
    bindings: {value: '<'},
    controller: function() {
      this.$onInit = function () {
        this.doubleValue = this.value * 2;
      };
    }
  });
```

If you don't have time to migrate the code at the moment, you can flip the
setting back to true:
```js
angular.module('myApp', [])
  .config(function($compileProvider) {
    $compileProvider.preAssignBindingsEnabled(false);
  })
  .component('myComponent', {
    bindings: {value: '<'},
    controller: function() {
      this.doubleValue = this.value * 2;
    }
  });
```
Don't do this if you're writing a library, though, as you shouldn't change
global configuration then.
mgol added a commit to mgol/angular.js that referenced this issue Nov 3, 2016
Fixes angular#15350

BREAKING CHANGE: Previously, $compileProvider.preAssignBindingsEnabled was
set to true by default. This means bindings were pre-assigned in component
constructors. In Angular 1.5+ the place to put the initialization logic
relying on bindings being present is the controller $onInit method.

To migrate follow the example below:

Before:

```js
angular.module('myApp', [])
  .component('myComponent', {
    bindings: {value: '<'},
    controller: function() {
      this.doubleValue = this.value * 2;
    }
  });
```

After:
```js
angular.module('myApp', [])
  .component('myComponent', {
    bindings: {value: '<'},
    controller: function() {
      this.$onInit = function() {
        this.doubleValue = this.value * 2;
      };
    }
  });
```

If you don't have time to migrate the code at the moment, you can flip the
setting back to true:
```js
angular.module('myApp', [])
  .config(function($compileProvider) {
    $compileProvider.preAssignBindingsEnabled(false);
  })
  .component('myComponent', {
    bindings: {value: '<'},
    controller: function() {
      this.doubleValue = this.value * 2;
    }
  });
```
Don't do this if you're writing a library, though, as you shouldn't change
global configuration then.
@mgol mgol closed this as completed in bcd0d4d Nov 3, 2016
ellimist pushed a commit to ellimist/angular.js that referenced this issue Mar 15, 2017
Fixes angular#15350
Closes angular#15352

BREAKING CHANGE: Previously, $compileProvider.preAssignBindingsEnabled was
set to true by default. This means bindings were pre-assigned in component
constructors. In Angular 1.5+ the place to put the initialization logic
relying on bindings being present is the controller $onInit method.

To migrate follow the example below:

Before:

```js
angular.module('myApp', [])
  .component('myComponent', {
    bindings: {value: '<'},
    controller: function() {
      this.doubleValue = this.value * 2;
    }
  });
```

After:
```js
angular.module('myApp', [])
  .component('myComponent', {
    bindings: {value: '<'},
    controller: function() {
      this.$onInit = function() {
        this.doubleValue = this.value * 2;
      };
    }
  });
```

If you don't have time to migrate the code at the moment, you can flip the
setting back to true:
```js
angular.module('myApp', [])
  .config(function($compileProvider) {
    $compileProvider.preAssignBindingsEnabled(false);
  })
  .component('myComponent', {
    bindings: {value: '<'},
    controller: function() {
      this.doubleValue = this.value * 2;
    }
  });
```
Don't do this if you're writing a library, though, as you shouldn't change
global configuration then.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant