# Angular directive with use of scope.$parent and$timeout

For the over eager people: check out this plunker

I create a directive which has to add buttons on top of input fields, to select the language you want to input.

This is used on forms, such as a product form. A product has translations (i.e. has a description that is language dependant).

Things I am not really happy with:

• I use $scope.$parent to get the required translation for the given field
• The use of the timeout to handle model info that arrives with a delay (from a web service)

for the people that took the time to read this: check out the example on plunker

The directive in question:

app.directive('translationMenu', function($compile,$timeout) {
return {
restrict: 'E',
scope: {
languages: '=',
defaultLanguage: '='
},
controller: function($scope,$element, $attrs) { // check if the current field is available in the given dictionary var checkFieldAvailability = function(l) { return$scope.$parent[$attrs.dictionary] && $scope.$parent[$attrs.dictionary][l] &&$scope.$parent[$attrs.dictionary][    l][$attrs.field]; } // check if the language is available in the dictionary, and if so, if the field is already translated. // is used to color the button text red var dictionaries = {};$scope.languages.forEach(function(l) {
dictionaries[l] = checkFieldAvailability(l);
});

// the muscles of this operation
// it will replace the input field with a clone of the original (and with ng-model filled out)
var inputElementTemplate = $element.next().clone(); var setInputField = function(lang) { var inputElement = inputElementTemplate.clone(); inputElement.attr('ng-model',$attrs.dictionary + '.' + lang + '.' + $attrs.field);$element.next().replaceWith(inputElement);
$compile(inputElement)($scope.$parent); }; // function used in the ng-click. // when navigating away, it will also check again if it needs transalation. var selectLanguage = function(lang) { var oldLang =$scope.selectedLanguage;
dictionaries[oldLang] = checkFieldAvailability(oldLang);
$scope.selectedLanguage = lang; setInputField(lang); }; // Dirty fix, this "ensures" that the dictionary is returned from the ajax request.$timeout(function() {
console.dir(dictionaries);
for (var lang in dictionaries) {
dictionaries[lang] = checkFieldAvailability(lang);
}
}, 300);

$scope.selectedLanguage =$scope.defaultLanguage;
$scope.selectLanguage = selectLanguage;$scope.dictionaries = dictionaries;

selectLanguage('en');
}
}
});


The View:

<div class="col-sm-5">
<input class="form-control" type="text" />
</div>


the controller:

function MyController($rootScope,$scope,$timeout) {$rootScope.allLanguages = ['en', 'nl', 'fr'];
$rootScope.currentUser = { DefaultLanguage: 'en' }; // Simulate slow-ish web service$scope.desc = {};
$timeout(function(){$scope.desc = {
'en': {
'name': 'Joseph',
'code': 'EN123'
},
'nl': {
'name': 'Jos',
'code': 'NL123'
}
};
}, 200);
}

• You are basically reading your attributes, then why not simply using $attrs provided instead of the fragile $scope.\$parent? – Dmitri Zaitsev Apr 19 '14 at 7:30