0

I am writing a directive that accesses a service to get the translated strings of the page. The service will make a call to the server on loading the page and get the strings back, it works with the controller displaying everything fine but doesn't work in the directive.

var blockUserAction = function () {
    return {
        restrict: 'AE',
        replace: 'true',
        scope: {
            theirId: "=theirId"
        },
        controller: function ($scope, translationsService) {
            translationsService.init(); //does http request. Already called on mod.run() so redundant here.
            $scope.caption = translationsService.translations.Conversation.OptionsMenu.BlockUser.value;

            $scope.btnClick = function () {
                debugger;
            };
        },
        template: "<a href='#' data-ng-click='btnClick()'>{{caption}}</a>"
    };
}

I have already called the translations.init() on the module.run() and works with the controller but I'm calling it here again to see if that helps... it doesn't really. I can see by debugging the btnClick() that once the service comes back with the strings the object is updated, so "translationsService.translations.Conversation.OptionsMenu.BlockUser.value" has its value but $scope.caption hasn't been updated.

I've been playing a bit with watch() and apply() but I have the feeling that I'm over complicating something that should be as simple as accessing the service, which is a singleton, and get the value.

theirId is a value that the parent controller sets on the directive tag through the view so the directive doesn't need to know about who is using it, it only needs the id and access to the services to use: translations and the profiles (removed this one to simplify atm) services .

Example:

<a block-user-action theirId="5"></a>

Does anyone know if I am supposed to call watch/apply or set it differently or this is just a bug as the main controller doesn't seem to have any problem with this but this other one does?

Also, this directive has been declared as part of the main module so it should have access to the service without problems:

app.directive('blockUserAction', blockUserAction);
app.run(function(messagingTranslations){
    messagingTranslations.init();
})

update

The translations.init():

var messagingTranslations = function (globalizationService) {
return {
    init: function () {
        globalizationService.setTranslations(this.translations);
    },
    translations: new function () {
    ...
    }
};
};

The service method called:

this.setTranslations = function (list) {
    var ids = getListOfIds(list);
    return getTranslationsFromServer(ids).then(function (response) {
        setTranslationValues(list, response);
        return list;
    });
}

update2

I've set a watch over translations...value and console.logged everything I can see that the directive is created, the scope assigned to empty string (default value) and after all of that has happened the watch fired... but there's no value?

var myDirective = function () {
    return {
        restrict: 'AE',
        replace: 'true',
        scope: {
            theirNoid: "=theirNoid"
        },
        controller: function ($scope, translationsService) {
            translationsService.init();
            console.log("init called");

            $scope.$watch('translationsService.translations.Conversation.OptionsMenu.BlockUser.value', function () {
                console.log('hey, myVar has changed!: ' + translationsService.translations.Conversation.OptionsMenu.BlockUser.value);
            });

            $scope.caption = translationsService.translations.Conversation.OptionsMenu.BlockUser.value;
            console.log("caption set");

            $scope.btnClick = function () {
                console.log('I clicked the button and the value is: ' + translationsService.translations.Conversation.OptionsMenu.BlockUser.value);
            };
        },
        template: "<a href='#' data-ng-click='btnClick()'>{{caption}} eee</a>"
    };
}

log:

init called
caption set
hey, myVar has changed!: 

But if I click the button the log is:

I clicked the button and the value is: Block user
5
  • If you write scope { theirId: '=theirId'} then you have to use their-id="5" and not theirId="5" Commented Apr 28, 2015 at 13:05
  • Thanks! You are right, I missed that. Though that's not the problem I have atm :( Commented Apr 28, 2015 at 13:11
  • If you have their-id in the anchor tag bound to a value on the scope than the directive will watch automatically. See fiddle for a little demo using a timeout to change the value in the controller scope. I would console.log everything you can on your translationsService to see if there is maybe something in there. Commented Apr 28, 2015 at 13:21
  • If your translationsService.init() were setup to return a promise than you might be better off. It's possible that the init doesn't return in the time you are setting the caption variable in the directive. However that should give you an error in the console. Commented Apr 28, 2015 at 13:23
  • 1
    @Ruben.Canton $watch fires on all $digest calls, one of those calls happens on initialization. This does not mean that the value of what your watching has necessarily changed. Commented Apr 28, 2015 at 14:53

1 Answer 1

0

Usually when you make a http request, the call will return immediately and the work is done in the back ground. Could it be that you are initializing translationsService.translations.Conversation.OptionsMenu.BlockUser.value to null just before making the http call and since the call returns immediately your rest of the code flows by setting $scope.caption to null. Of course translationsService.translations.Conversation.OptionsMenu.BlockUser.value will be updated at a later time, but $scope.caption will still hold null.

Again this is based on the assumption that you are using a http call in translationsService.init() and not treating the returned promise properly.

Sign up to request clarification or add additional context in comments.

3 Comments

The translations object is a structure ending in key-value pair nodes with an id (key) and a value. It is initialized with values set to an empty string: ''
I am making an http call, let me add it to the question to make it easier to look at.
As suspected, in your service method call this.setTranslations, you are just making the http call. You should consider returning promise returned by the http call use it to update the dependent variables. I suggest you read w3schools.com/angular/angular_http.asp and angular official documentation on $http - hope this helps

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.