Mars Robertson
Mars Robertson

Reputation: 13233

How to access Angular scope in Select2 "change" handler?

I would really like to know how to set the right property for the right object.

enter image description here

Currently in the "change" event handler I have no knowledge of the scope I'm in. Effectively I don't know which location I should update.

Plunker: http://plnkr.co/edit/T4aBzND7VV2gCkui0I7P?p=preview

Code highlights

app.controller('MyCtrl', ['$scope', function ($scope) {
    $scope.locations = ['Paris', 'London'];
}]);

app.directive('timezone', function(timezones) {
    var _updateSetting = function(e) {
        console.log(e.target.value);
        // How do I update objects in my scope?
        // (cannot access here)
    };
    return {
        restrict: 'E',

        link: function(scope, el, attrs) {
            el.select2( { data: timezones.get() } ).on("change", _updateSetting);
        },

        template : "<input type='hidden' class='timezoneSelector' style='width: 100%;'>"
    }
});

app.factory('timezones', function() {
    var timezones = ["Europe/London", "Europe/Paris"];
    var timezonesSelect = timezones.map(function(obj) { return {id: obj, text: obj }; } ); 
    // preparing data so it is ready to use for select2
    return {
        get : function() { return timezonesSelect; }
    }
});

Note: I don't want to use https://github.com/angular-ui/ui-select2 I want to stay closer to my code, be in control :)

Note: Select2 constructs some off-screen divs, and I could potentially lookup $(e.target).parent().text() but it just look ugly to me

If you have any suggestions how to do this properly in "angular way" - let me know in the answers / comments :)

Upvotes: 1

Views: 989

Answers (2)

YK1
YK1

Reputation: 7622

You could access the scope by passing it as parameter as in @urban_racoons' answer. However, as you are using events outside Angular, you will have to let it know you have updated scope by using $apply.

app.directive('timezone', function(timezones) {
        var _updateSetting = function(scope, e) {
            console.log(e.target.value);
            // now you can update scope
        };

        return {
            restrict: 'E',

            link: function(scope, el, attrs) {
                el.select2( { data: timezones.get() } ).on("change", function(e) {
                  scope.$apply( function() {
                    _updateSetting(scope, e);
                  });
                });
            },

            template : "<input type='hidden' class='timezoneSelector' style='width: 100%;'>"
        }
    });

Upvotes: 4

urban_raccoons
urban_raccoons

Reputation: 3497

I'm not sure if this is my favorite way of doing this, but it should work for what you're interested in:

app.directive('timezone', function(timezones) {
    var _updateSetting = function(locations) {
        console.log(locations);

    };

    return {
        restrict: 'E',

        link: function(scope, el, attrs) {
            el.select2( { data: timezones.get() } ).on("change", function() {
              _updateSetting(scope.locations);
            });
        },

        template : "<input type='hidden' class='timezoneSelector' style='width: 100%;'>"
    }
});

Upvotes: 1

Related Questions