johnpapa / angular-styleguide

Angular Style Guide: A starting point for Angular development teams to provide consistency through good practices.
http://johnpapa.net
MIT License
23.84k stars 4.15k forks source link

dataService calls when inside page controllers vs component/directive controllers. #835

Open kodizen opened 7 years ago

kodizen commented 7 years ago

I have a question open on stack overflow about this, but it basically boils down to this:

We have various pages containing directives / components.

At the minute, all our dataService calls are done within the pageController, then passing data to each directive via attr's.

My proposal is to shift the dataService calls to within the directives controller, thereby separating the component completely from its parent controllers, and means we can just call a component using a single html tag.

Is there a problem with architecting it in this manner?

This is the question on stack overflow which contains some code examples -> https://stackoverflow.com/questions/44258446/angular-project-architecture-controllers-directives-style-guides

MarcLoupias commented 7 years ago

If your component is a presentational component (like a dumb list), you should not put any logic in it and passing the data directly via attr is the good way.

If your component is a container component (a view part reused in different views, for example a card with a list and some buttons or a view itself), you should run API calls in the component init life cycle event. Running API calls should be done through angular services, so in fact you are just resolving the promise in the component controller to set data state (the pure data binding) et ui state (loaders).

kodizen commented 7 years ago

Thanks @MarcLoupias thats what I was thinking. Our components all need to be reused throughout the application, hence the thinking to put the call to the dataService inside the component controller, below is an example of one of our components, ignore any syntactical errors:

(function() {
    'use strict';

    angular
        .module('front')
        .directive('component', component);

    function Component() {
        var directive = {
            restrict: 'E',
            templateUrl: 'app/components/component/component.html',
            scope: {
                ffModel: '='
            },
            controller: ComponentController,
            controllerAs: 'c',
            bindToController: true
        };

        return directive;

        /** @ngInject */
        function ComponentController(componentService) {

            var vm = this;
            vm.component = {};

            activate();

            function activate() {
                getComponentData();
            } // end activate()

            /* get component data */
            function getComponentData() {

               /* The componentService is the data service responsible for providing data to the directive, previously this was living in the pagecontroller, meaning we were copy pasting it everytime we wanted to use that component in a page /*
               componentService.getComponentData().then(function(response) {
                    vm.component.data = response.data;
                    vm.component.lastModified = new Date(response.timestamp * 1000);
                    return vm.component;
                });

            }

            vm.getComponentData = getComponentData;
        }

    }

})();

now, anytime I need to use this component, I can just use <component></component> without needing to plug in the data service call everytime