angularjscomponentsangularjs-bindings

Binding an integer to AngularJS 1.5 component


When using attribute binding in components, the data passed to the controller is always a string. I'm trying to pass an integer, however, and am having trouble converting it from a string and having the conversion stick.

I've tried saving the data as an integer in $onInit() but outside of this function, the data returns to its original state (type and value). I understand that components should not modify the data passed in as a general rule, but since this is an attribute binding, and the data is passed by value, I didn't think that applied.

function IntegerBindingController() {
  this.$onInit = function() {
    // Assuming 'number="2"' in the HTML
    // This only changes the data inside this function
    this.number = parseInt(this.number)
    this.typeofNumber = typeof this.number // evaluates to 'number'
    this.simpleAdd = this.number + 5 // evaluates to 7
    this.dataAdd = this.numberOneWay + 5
    console.log(this)
  }

  this.test = function() {
    // this.number is a string inside this function
    this.typeofNumber = typeof this.number // evaluates to 'string'
    this.simpleAdd = this.number + 5 // evaluates to 25
  }
}

I can solve this by copying the data to a new property on the controller, but I'm curious if someone can explain what's happening here. See this Plunker for a working example of the issue.


Solution

  • The solution I ended up going with was to use $onChanges to handle the bound data values. In my case, at least one of the values could potentially change after an async call in the parent component, so this made sense overall. As Prinay Panday notes above, the @ binding always comes through as a string. The $onInit() method guarantees that bindings will be available, but it doesn't guarantee that they will change, so even if you change the value on the component, Angular can change it later. That's another reason why the documentation recommends copying the bound values to a local variable if you need to manipulate them at all. As for the $onChanges() solution, it would look like this

    function IntegerBindingController() {
      this.$onChanges(changes) {
        if (changes.number && changes.number.currentValue) {
            this.number = parseInt(changes.number.currentValue)
        }
      }
    
      this.test = function() {
        this.typeofNumber = typeof this.number // evaluates to 'number'
        this.simpleAdd = this.number + 5 // evaluates to 7 (assuming this.number was 2)
      }
    }