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
Let me know if you need any more information / explanation.
The directive in question:
app.directive('translationMenu', function($compile, $timeout) {
return {
restrict: 'E',
scope: {
languages: '=',
defaultLanguage: '='
},
templateUrl: 'translation-menu.html',
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">
<translation-menu languages="allLanguages" default-language="currentUser.DefaultLanguage" field="name" dictionary="desc" ></translation-menu>
<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);
}
$attrs
provided instead of the fragile$scope.$parent
? – Dmitri Zaitsev Apr 19 '14 at 7:30