2

I'm creating a big component based angular 1.5.8 application. There are about 18 different components within a parent component. For this purpose, each components template has inputs which is a part of parent component form. So far everything works fine. What I'm stuck at, and really in need of logic, is how to detect the changes made to the inputs in each component so the data can be saved in shared service for the parent component to fetch before sending the form data to the server.

From the parent component

<form name="claimForm" novalidate>
    <!-- Section Title  -->
    <section name="Add new claim" class="section-background section animated fadeIn" ng-cloak>

        <!-- Pharmacy Info -->
        <pharmacy-info claim-form="claimForm"></pharmacy-info>

    </section>
</form>

PharmacyInfo has just a simple inputs

<md-input-container flex-gt-sm="70">
    <label>Pharmacy Name</label>
    <input type="text"
            flex
            tabindex="4"
            id="pharmacyName"
            name="pharmacyName"
            md-maxlength="80"
            aria-label="Pharmacy Name"
            ng-model="$ctrl.pharmacy.name" />
    <div ng-messages="$ctrl.claimForm.pharmacyName.$error">
        <div ng-message="md-maxlength">
            Pharmacy name is too long!
        </div>
    </div>
</md-input-container>

Pharmacy Component

(function () {
    'use strict';

    angular.module('sempp')
        .component('pharmacyInfo', {
            templateUrl: 'Scripts/src/views/pharmacy/pharmacy.info.template.html',
            controller: PharmacyInfoComponentController,
            bindings: {
                claimForm: '<'
            }
        });

    PharmacyInfoComponentController.$inject = ['PharmacyService']

    function PharmacyInfoComponentController(PharmacyService) {
        var $ctrl = this;


        $ctrl.$doCheck = function () {

            //console.log($ctrl.pharmacy);
            PharmacyService.setPharmacy($ctrl.pharmacy);
        }


    }// end controller function

})();

The problem I'm having is that I can't have an "update" button on each component for users to click everytime they enter the value in the form. It won't be too user friendly.

The other issue I'm running into is using $onChanges. It's not detecting any changes made to the form in the Child Component. Not sure how to make that happen. I'm still reading the docs though.

However, if I use $doCheck, it does detect the changes, but it's running everytime I make a change on any more the form. Now, with about 18 components and many input forms in each components, I think that'll just slow down the application.

What're my choices? How can I make it seamless such that when the user enters the value, that value is either saved in shared services, or saved in parent component object (whichever is better). I will then need to send the data to the database to be inserted.

Kuni
  • 817
  • 1
  • 9
  • 24
  • https://docs.angularjs.org/guide/component **Take a look at this documentation which might clarify most of your queries** – Aravind Nov 02 '16 at 00:44

2 Answers2

1

Use the ng-change directive on inputs:

<md-input-container flex-gt-sm="70">
    <label>Pharmacy Name</label>
    <!-- USE ng-change directive -->
    <input type="text"
            ng-change="$ctrl.updatePharmacyService()"               
            flex
            tabindex="4"
            id="pharmacyName"
            name="pharmacyName"
            md-maxlength="80"
            aria-label="Pharmacy Name"
            ng-model="$ctrl.pharmacy.name" />
    <div ng-messages="$ctrl.claimForm.pharmacyName.$error">
        <div ng-message="md-maxlength">
            Pharmacy name is too long!
        </div>
    </div>
</md-input-container>

The ng-change directive evaluates its AngularJS Expression only the when the user enters an input. This will have less overhead than using the $doCheck function which evaluates every digest cycle.

For more information, see SO: AngularJs 1.5 - Component does not support Watchers, what is the work around?

Community
  • 1
  • 1
georgeawg
  • 48,608
  • 13
  • 72
  • 95
  • This is good. For some reason, i did not think about `ng-change`, and I have used it in my app in a few places. I guess I was only thinking in `$watch` view. Thanks. – Kuni Nov 02 '16 at 01:22
0

Make sure your parent component can view the changes made in your child component and you can do something like this within your parent:

$scope.$watch(function() {
   return ctrl.pharmacy
}, function(){
    // do your updates here within the parent function
});

Of course this means you'll have to inject $scope into your parent controller, but I've typically found this the easiest way to handle this.

Forbsey1
  • 155
  • 8
  • 1
    So, this means I'll have to do $watch or $watchcollection for each and every objects I have for each components in the Parent Controller. If it was only a few objects, then I can see this being a possibility. With about 18 components, so 18 objects, and this can grow in the future, there'll be a lot of $watch or $watchcollection. Or am I mistaken? – Kuni Nov 01 '16 at 21:44