I'am using Angular JS for a multipage registration site.
(With this great tutorial: http://scotch.io/tutorials/javascript/angularjs-multi-step-form-using-ui-router)
I now want to use the Bootstrap Formhelper country picker in one of the pages (http://bootstrapformhelpers.com/country/#jquery-plugins) like this:
<div ui-view>
...
<div class="bfh-selectbox bfh-countries" data-country="AT" data-flags="true"></div>
...
</div>
But it doesn't work. The country picker doesn't show up (height: 0).
If i put the country picker outside of de ui-view div the picker works. But i want to have it inside the ui-view div:
<div class="bfh-selectbox bfh-countries" data-country="AT" data-flags="true"></div>
<div ui-view>
...
</div>
For some reason the angularJS directive ui-view is breaking the country picker.
Has anyone an idea why this happens?
Best regards
Yannick
EDIT:
My imports:
<link rel="stylesheet" href="assets/css/bootstrap.min.css">
<link rel="stylesheet" href="style.css">
<script src="assets/js/angular.js"></script>
<script src="assets/js/angular-animate.js"></script>
<script src="assets/js/angular-ui-router.min.js"></script>
<script src="assets/js/angular-animate.js"></script>
<script src="app.js"></script>
<!-- Bootstrap -->
<script src="assets/js/jquery-1.11.1.min.js"></script>
<link rel="stylesheet" href="assets/css/bootstrap-theme.min.css">
<script src="assets/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="assets/css/bootstrap-formhelpers.min.css">
<script src="assets/js/bootstrap-formhelpers.min.js"></script>
<script src="assets/js/bootstrap-formhelpers-states.js"></script>
<script src="assets/js/bootstrap-formhelpers-countries.de-DE.js"></script>
<script src="assets/js/bootstrap-formhelpers-countries.js"></script>
EDIT2:
i now use a directive for the initialization. strange think is that this code works:
angular.module("formApp").directive('nationpicker', function ($parse) {
return {
restrict: 'A',
replace: false,
transclude: false,
link: function (scope, element, attrs) {
element.append('<select id="countries1" class="form-control"></select>');
$('#countries1').bfhcountries({flags:true})
}
};
But this code doesnt work:
angular.module("formApp").directive('nationpicker', function ($parse) {
return {
restrict: 'A',
replace: false,
transclude: false,
link: function (scope, element, attrs) {
element.append('<div id="country" class="bfh-selectbox bfh-countries" data-country="AT" data-flags="true"></div>');
$('#country').bfhcountries({flags:true})
}
};
In fact these are only the different examples from the Bootstrap Formhelper (see link at the top)
the first one is the 3. example the second code which doesn't work is from my prefered 4.Example.
Can anyone please tell me why this is not working for the 4.Example?
Thank you for reaching out to me via email. I have looked over your code and made a few changes to resolve the problem. For sake of others who may have a similar problem I will follow up here so that we can close this issue.
The problem is not with the ui-view directive, but in the nationpicker directive. Here is the updated directive code:
angular.module("formApp").directive('nationpicker', function ($parse) {
// The directive has been rewritten to work properly
return {
restrict: 'A', // It is an attribute
require: '?ngModel', // It uses ng-model binding
scope: {
ngModel: '='
},
link: function (scope, elem, attrs, ctrl) {
// Add the required classes
elem.addClass('bfh-countries');
elem.addClass('bfh-selectbox');
// First we initialize the selectbox with the desired options
elem.bfhselectbox({
filter: (elem.attr('data-filter') == 'true') ? true : false
}).on('change.bfhselectbox', function() {
// Listen for the change event and update the bound model
return scope.$apply(function () {
return scope.ngModel = elem.val();
});
});
// Initialize the countries with the desired options
return elem.bfhcountries({
flags: (elem.attr('data-flags') == 'true') ? true : false,
country: scope.ngModel || 'AT'
});
}
};
});
In order for this to work a couple of changes had to be made to your element in the HTML
<div nationpicker id="country" data-flags="true" data-filter="true" ng-model="nation"></div>
Notice that the classes are no longer included. This is handled by the directive now. I also opted to bind the country in the controller scope rather than using the data-country attribute. This was as simple as adding $scope.nation = 'AT'; in the controller.
I also had to move all of your angular related script tags below the bootstrap and form-helper scripts.
<!-- Bootstrap -->
<script src="assets/js/jquery-1.11.1.min.js"></script>
<link rel="stylesheet" href="assets/css/bootstrap-theme.min.css">
<script src="assets/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="assets/css/bootstrap-formhelpers.min.css">
<script src="assets/js/bootstrap-formhelpers.min.js"></script>
<script src="assets/js/bootstrap-formhelpers-states.js"></script>
<script src="assets/js/bootstrap-formhelpers-countries.de-DE.js"></script>
<!--<script src="assets/js/bootstrap-formhelpers-countries.js"></script>-->
<!-- moved all angular related scripts to here -->
<script src="assets/js/angular.js"></script>
<script src="assets/js/angular-animate.js"></script>
<script src="assets/js/angular-ui-router.min.js"></script>
<script src="assets/js/angular-animate.js"></script>
<script src="app.js"></script>
<script src="directive.js"></script>
I will also follow up with you via email and I hope this helps you continue with your project.
To have two-way binding work you can modify directive code as below:
myApp.directive('nationpicker', function ($parse) {
return {
restrict: 'A', // It is an attribute
require: '?ngModel', // It uses ng-model binding
scope: {
ngModel: '='
},
link: function (scope, elem, attrs, ctrl) {
// Add the required classes
elem.addClass('bfh-countries');
elem.addClass('bfh-selectbox');
// First we initialize the selectbox with the desired options
elem.bfhselectbox({
filter: (elem.attr('data-filter') == 'true') ? true : false
}).on('change.bfhselectbox', function () {
// Listen for the change event and update the bound model
return scope.$apply(function () {
return scope.ngModel = elem.val();
});
});
scope.$watch('ngModel', function (newVal, oldVal) {
if (newVal != oldVal) {
elem.find("input").val(newVal);
elem.find("span.bfh-selectbox-option").empty().append('<i class="glyphicon bfh-flag-' + newVal + '"></i>' + BFHCountriesList[newVal]);
}
});
// Initialize the countries with the desired options
return elem.bfhcountries({
flags: (elem.attr('data-flags') == 'true') ? true : false,
country: scope.ngModel
});
}
};
});