Sergii Vorobei
Sergii Vorobei

Reputation: 1487

Angular 1.5 component issue

I have decided to create component like separate widget, e.g. parent passes config to it and component fetches data (the parent does not need data from the child). But there some cases, e.g some update in parent, which can affect displayed data. So I would like kind of say to child: refetch the data, while config remaining the same. But this won't cause $onChanges callback to fire, as link to config object is the same, so I fixed it in a hacky way:

vm.childConfig = _.assign({}, vm.childConfig);

This works fine, but ugly, as for me. Are there any better solutions for it? (creating $watch, emitting events seem to be even worse solution)

Some example code:

<parent-component>
        <child-component config="childConfig"></child-component>
</parent-component>

JS:

function ParentComponentController () {
    vm.childConfig = {show: true, ...}

    vm.onItemDelete = function () {
      vm.childConfig = _.assign({}, vm.childConfig); // I want to call `fetchData` so I force child $onChanges to fire.
    }
}

function ChildComponentController () {
   vm.$onInit = function () {
      fetchData()
   }
   vm.$onChanges = function () {
      // will not fire if will not change the config object reference
      fetchData(changes)
   }
}

So I want something like force child to call $onChanges

P.S. I don't like the idea for the child to be dumb component (parent passes fetched data to it), of course it will fix this issue, but the data is only needed in the child, and it will make parent component even fatter.

Upvotes: 2

Views: 74

Answers (1)

camden_kid
camden_kid

Reputation: 12813

Is this the kind of thing you mean?

JS

angular.module("app")
    .component(
        "ChildComponent",
        {
            controller: ChildComponentCtrl,
            bindings: {
                config: "<",
                update: "<"
            }
        }
    );


function ChildComponent () {
    var init = false;

    function init() {
        // Set up config
        init = true;
    }

    function update() {
        // config remains the same but do something else
    }

    this.$onChanges = function () {
        if (angular.isDefined(this.config) && !init) {
            init();
        }
        else if (angular.isDefined(this.update)) {
            update();
        }
    };
}

Markup

<parent-component>
    <child-component config="childConfig" update="update"></child-component>
</parent-component>

Edit - To make sure update works more than once do the following:

ChildComponent

    this.$onChanges = function () {
        if (angular.isDefined(this.config) && !init) {
            init();
        }
        else if (angular.isDefined(this.update) && update) {
            update();
        }
    };

ParentComponent

function doUpdate() {
    this.update = true;
    // Rest update so that it works next time
    $timeout(function () {
        this.update = false;
    });
}

Upvotes: 1

Related Questions