Ludwig
Ludwig

Reputation: 1791

How to get value from directive in Angular

I neeed to pass a value from this part of the code in my directive to a controller, but not sure how to achieve that:

       if (!scope.multiple) {
          scope.model = value;
          console.log(scope.model);
          return;
        }

I get the value in the console.log, I just don't know how to pass it to the controller. This is the complete directive:

angular.module('quiz.directives')
.directive('fancySelect', function($rootScope, $timeout) {
  return {
    restrict: 'E',
    templateUrl: 'templates/directives/fancySelect.html',
    scope: {
      title: '@',
      model: '=',
      options: '=',
      multiple: '=',
      enable: '=',
      onChange: '&',
      class: '@'
    },
    link: function(scope) {
      scope.showOptions = false;
      scope.displayValues = [];

      scope.$watch('enable', function(enable) {
        if (!enable && scope.showOptions) {
          scope.toggleShowOptions(false);
        }
      });

      scope.toggleShowOptions = function(show) {
        if (!scope.enable) {
          return;
        }

        if (show === undefined) {
          show = !scope.showOptions;
        }

        if (show) {
          $rootScope.$broadcast('fancySelect:hideAll');
        }

        $timeout(function() {
          scope.showOptions = show;
        });
      };

      scope.toggleValue = function(value) {
        if (!value) {
          return;
        }

        if (!scope.multiple) {
          scope.model = value;
          console.log(scope.model);
          return;
        }

        var index = scope.model.indexOf(value);
        if (index >= 0) {
          scope.model.splice(index, 1);
        }
        else {
          scope.model.push(value);
        }

        if (scope.onChange) {
          scope.onChange();
        }
      };

      scope.getDisplayValues = function() {
        if (!scope.options || !scope.model) {
          return [];
        }

        if (!scope.multiple && scope.model) {
          return scope.options.filter(function(opt) {
            return opt.id == scope.model;
          });
        }

        return scope.options.filter(function(opt) {
          return scope.model.indexOf(opt.id) >= 0;
        });
      };

      $rootScope.$on('fancySelect:hideAll', function() {
        scope.showOptions = false;
      });
    }
  };
});

Updated

I tried to do as suggested in the answers by @Zidane and defining my object first in the controller like this:

$scope.year = {};

var saveUser = function(user) {
   $scope.profilePromise = UserService.save(user);
console.log($scope.year);

This is the template:

<fancy-select
            title="Klassetrinn"
            model="year"
            options="years"
            enable="true"
            on-change="onChangeYears()"
            active="yearsActive"
            name="playerYear"
            form-name="registerForm"
          >
          </fancy-select>

But I got an empty object in that case.

When I define my objects like this I get the right value in the controller but in the view the title is not being displayed anymore:

$scope.search = {
    years: []
  };

var saveUser = function(user) {
    $scope.profilePromise = UserService.save(user);
console.log($scope.search.years);

<fancy-select
            title="Klassetrinn"
            model="search.years"
            options="years"
            enable="true"
            on-change="onChangeYears()"
            active="yearsActive"
            name="playerYear"
            form-name="registerForm"
          >
          </fancy-select>

Upvotes: 0

Views: 130

Answers (2)

steven.westside
steven.westside

Reputation: 284

As you defined an isolated scope for your directive like this

scope: {
      ...
      model: '=',
      ...
    },

you give your directive a reference to an object on your controller scope. Declaring the directive like <fancy-select model="myModel" ....></fancy-select> you pass your directive a reference to scope.myModel on your controller. When you modify a property on the scope.model object in your directive you automatically modify the same property on the scope.myModel object in your controller.

So you have to do

myApp.controller('myController', function($scope) {
  ...
  $scope.myModel = {};
  ...
}

in your controller and in your directive just do

if (!scope.multiple) {
  scope.model.value = value;
  return;
}

Then you can get the value in your controller via $scope.myModel.value.

For clarification: You have to define an object on your controller and pass the directive the reference for this object so that the directive can follow the reference and doesn't mask it. If you did in your directive scope.model = 33 then you would just mask the reference passed to it from the controller, which means scope.model wouldn't point to the object on the controller anymore. When you do scope.model.value = 33 then you actually follow the object reference and modify the object on the controller scope.

Upvotes: 1

xelilof
xelilof

Reputation: 456

you can use services or factories to share data between your angular application parts, for example

    angular.module('myapp').factory('myDataSharing', myDataSharing);

function myDataSharing() {


    var sharedData = {
        fieldOne: ''
    };

    return {
        setData: setData,
        getData: getData,
    };


    function setData(dataFieldValue) {
        sharedData.fieldOne = dataFieldValue;
    };


    function getData() {
        sharedData.fieldOne
    };


    directive:
        myDataSharing.setData(dataValue);

    controller:
angular.module('myapp').controller('myController' ['myDataSharing'], function(myDataSharing) {
            var myDataFromSharedService = myDataSharing.getData();
        }

Upvotes: 0

Related Questions