Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.component helper #662

Closed
xavhan opened this issue Feb 11, 2016 · 5 comments
Closed

.component helper #662

xavhan opened this issue Feb 11, 2016 · 5 comments

Comments

@xavhan
Copy link
Contributor

xavhan commented Feb 11, 2016

With the release of Angular 1.5 we can use the .component() shortcut to create component directives.
Do you have any suggestions in the way to use it ?

I have been a big follower of your styleguide for some time and here is how I usually write them.

Small ones, without the need of a controller, I like to write the template inside the same file as the return value of a hoisted function

(function() {
  'use strict';

  var componentConfig = {
    template: generateTemplate(),
    bindings: {
      kpiVal: '=',
      kpiLabel: '=',
    },
  };

  angular
    .module('app.utils.kpi')
    .component('sfKpi', componentConfig);

  //
  function generateTemplate() {
    return [
      '<div class="sf_kpi">',
      '  <div class="sf_kpi__number">{{ $ctrl.kpiVal }}</div>',
      '  <div class="sf_kpi__label">{{ $ctrl.kpiLabel }}</div>',
      '</div>',
    ].join('');
  }
}());

For more advanced ones I like to put the template in a separate file and use 'templateUrl' property.

(function() {
  'use strict';

  var componentConfig = {
    templateUrl: 'components/active-places/active-places.widget.html',
    controller: controller,
  };

  angular
    .module('app.widget.activeplaces')
    .component('activePlaces', componentConfig);

  /* @ngInject */
  function controller($log, activityService) {
    var vm = this;

    vm.activities = [];
    vm.isLoading = true;

    vm.doFunnyStuff = doFunnyStuff;

    activate();

    function activate() {
      $log.info('👊 activating activePlaces component');

      activityService.getActivites()
        .then(fetchData)
        .catch(handleError)
        .finally(stopLoader);

      //
      function fetchData(activities) {
        vm.activities = activities;
        $log.log('👓 activePlaces activities fetched: ', activities);
      }
      function handleError(err){
        $log.error('💥 problem fetching activePlaces data', err);
      }
      function stopLoader() {
        vm.isLoading = false;
        $log.info('💪 activePlaces component started');
      }
    }

    // methods
    function doFunnyStuff() {
      vm.activities.push('yolo');
    }

  }

}());

I am also curious about your opinion about the $onInit hook and how do you think components should be tested.

Thanks

@softsimon
Copy link

(function() {
  'use strict';

  var componentConfig = {
    bindings: {
        data: '<'
    },
    templateUrl: 'components/active-places/active-places.widget.html',
    controller: 'ActivePlacesController as vm',
  };

  angular
    .module('app.widget.activeplaces')
    .component('activePlaces', componentConfig)
    .controller('ActivePlacesController', ActivePlacesController);

  /* @ngInject */
  function ActivePlacesController($log, activityService) {
    var vm = this;

    vm.activities = [];
    vm.isLoading = true;

    vm.doFunnyStuff = doFunnyStuff;

    // methods
    function doFunnyStuff() {
      vm.activities.push('yolo');
    }

  }

}());

This way the controller can be tested.
Personally I prefer this way.

(function() {
  'use strict';

    angular
        .module('app.widget.activeplaces')
        .component('activePlaces', {
            bindings: {
                data: '<'
            },
            templateUrl: 'components/active-places/active-places.widget.html',
            controller: 'ActivePlacesController as vm',
         })
        .controller('ActivePlacesController', ActivePlacesController);

    function ActivePlacesController($log, activityService) {
        var vm = this;

        vm.activities = [];
        vm.isLoading = true;

        vm.doFunnyStuff = doFunnyStuff;

        // methods
        function doFunnyStuff() {
          vm.activities.push('yolo');
        }
    }

}());

@gkalpak
Copy link

gkalpak commented Feb 17, 2016

This way the controller can be tested.

@softsimon: v1.5.0 introduces ngMock#$componentController, so you don't have to register the controller separately for testability's sake 😃

@attilacsanyi
Copy link

I can second, thx @gkalpak . @softsimon you can simply skip this line from above:
.controller('ActivePlacesController', ActivePlacesController);

I also big fan of this style guide.

@xavhan for $onInit I would use this way in your example:

vm.$onInit = activate;

function activate() {
}

I might call it init and not activate from v1.5.0.

I also curious what @johnpapa think about this, appreciate.your guidance in advance.

@juristr
Copy link

juristr commented Mar 9, 2016

👍 for

vm.$onInit = activate;

function activate() {
}

@johnpapa
Copy link
Owner

johnpapa commented Sep 5, 2016

closed for #766 to be the place for component discussion

@johnpapa johnpapa closed this as completed Sep 5, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants