AngularJS + Bootstrap: dropdown list not populating correctly - angularjs

I could sure use some guidance on this... I've got a simple Bootstrap dropdown list that doesn't seem to be populating properly, whether I use ng-repeat to retrieve the list from the model OR list the items manually.
<div class="row">
<div class="col-md-4 col-md-offset-4">
<div class="input-group-btn">
<button type="button" class="btn btn-info" ng-click="submit()"> {{selectedAction.name}}</button>
<button type="button" class="btn btn-default btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <span class="caret"></span></button>
<ul class="dropdown-menu dropdown-menu-right">
<li ng-repeat="action in actions">
{{action.name}}
</li>
</ul>
</div><!-- /btn-group -->
</div><!-- /.col-lg-4 -->
</div><!-- /.row -->
Also, more importantly, the ng-click directive should change the DOM via normal binding, but this doesn't seem to work either.
var DropDownApp = angular.module('DropDownApp', []);
DropDownApp.controller('DropDownCtrl', ['$scope', function($scope) {
$scope.actions = [
{id: 'action1', name: 'Action 1'},
{id: 'action2', name: 'Action 2'},
{id: 'action3', name: 'Action 3'}
];
$scope.selectedAction = $scope.actions[0];
$scope.setAction = function(action) {
$scope.selectedAction = action;
console.log("selected==>", $scope.selectedAction);
$scope.submit();
};
$scope.submit = function() {
console.log($scope.selectedAction.id);
};
}]);
You can see the code behavior here: Plunker

Please note the points below:
Include ui.bootstrap dependancy in app.js to work with Angular ui-bootstrap.
This directive is composed by three parts:
uib-dropdown which transforms a node into a dropdown.
uib-dropdown-toggle which allows the dropdown to be toggled via click. This directive is optional.
uib-dropdown-menu which transforms a node into the popup menu.
Each of these parts need to be used as attribute directives.
Please find the working plunker here: http://plnkr.co/edit/v2uonllub3GsTFUxdFys?p=preview
Cheers!

Related

AngularJS binding to Bootstrap Popover attribute

I'm trying to dynamically populate the data-title and the data-content of a Bootstrap popover from a JSON create in an AngularJS controller.
Controller Snippet:
$scope.popoverContent = {name: {title: "title", content: "content"}}
HTML Snippet:
<span class="glyphicon glyphicon-question-sign"
aria-hidden="true"
data-toggle="popover"
data-trigger="hover"
data-title="{{popoverContent.name.title}}"
data-placement="right"
data-content="{{popoverContent.name.content}}">
</span>
I'm getting the exact text between the double quotes in the HTML page, {{popoverContent.name.title}}.
I've tried with ng-attr-data-title="{{popoverContent.name.title}}" but in this case, the title does not get displayed at all.
Other variables set in the controller are getting displayed properly in the HTML page.
Is is possible to implement something like this?
Try this code
var demo = angular.module('demo', []);
demo.controller('loadData', function($scope){
$scope.uploadData = function() {
$scope.popoverContent = {name: {title: "title", content: "content"}};
};
});
demo.directive("popUps",function(){
return {
restrict:'E',
replace: true,
transclude: false,
template:'<span class="glyphicon glyphicon-question-sign" aria-hidden="true" data-toggle="popover" data-trigger="hover" data-title="{{popoverContent.name.title}}" data-placement="right" data-content="{{popoverContent.name.content}}">data-title:{{popoverContent.name.title}}</br>data-content:{{popoverContent.name.content}}</span>'
};
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js"></script>
<div ng-app='demo'>
<div ng-controller='loadData'>
<button ng-click='uploadData($event)' >show</button>
<div>
<pop-ups></pop-ups>
</div>
</div>
</div>

angular bootstrap accordion is-open scope

I am trying to figure out how to close an accordion group from a button within the group.. seems like it should be easy.. but looks to be something with the scope being defined only within the group and not available in the controller? in the code snippet below the first button is how I would like to close the accordion group. The second button works.
Here is a simple plunkr on what I'm working on https://plnkr.co/edit/bghRaioszH3SZmiWxcoH?p=preview
<uib-accordion close-others="true" ng-controller="testCtrl">
<uib-accordion-group panel-class="panel-primary" is-open="status.isOpen">
<uib-accordion-heading>
Open: {{ status.isOpen }}
<i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': status.isOpen, 'glyphicon-chevron-right': !status.isOpen}"></i>
</uib-accordion-heading>
<button class="btn btn-warning" ng-click="close()">Cancel</button>
<button class="btn btn-warning" ng-click="status.isOpen=!status.isOpen">Cancel</button>
</uib-accordion-group>
</uib-accordion>
To access the status of an accordion group through your controller's scope, you need to do something like this:
Move ng-controller="testCtrl" to the <body> element
Define status explicitly in your controller's scope:
.controller('testCtrl', function($scope) {
$scope.status = {
isOpen: true
}
$scope.close = function(){
$scope.status.isOpen = false;
};
});

UI-bootstrap - Add a tab and select it by default

I'm trying to make a tab system using ui-bootstrap.
It's nearly fine but I'm still having trouble with the last tab when I add one.
Adding one tab is OK, but if I want to select it automatically once it's created, I've got a weird behaviour :
One tab added : fine
One tab added : not selected
One tab added : fine
One tab added : not selected
and so on ...
I've made a plunkr to demonstrate my bug, just click multiple times on the "+" button and have a look to which tab is selected.
Here's the JS code :
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('TabsDemoCtrl', function($scope) {
$scope.tabs = [{
title: 'Dynamic Title 1',
content: 'Dynamic content 1',
active: false
}, {
title: 'Dynamic Title 2',
content: 'Dynamic content 2',
active: false
}];
$scope.addTab = function() {
$scope.tabs.push({
title: 'Dynamic Title ' + ($scope.tabs.length + 1),
content: 'Dynamic content ' + ($scope.tabs.length + 1)
});
$scope.active = $scope.tabs.length - 1;
};
});
Here's the HTML code :
<div ng-controller="TabsDemoCtrl">
<p>Select a tab by setting active binding to true:</p>
<p>
<button type="button" class="btn btn-default btn-sm" ng-click="active = 1">Select second tab</button>
<button type="button" class="btn btn-default btn-sm" ng-click="active = 2">Select third tab</button>
</p>
<p>
<button type="button" class="btn btn-default btn-sm" ng-click="tabs[1].disabled = ! tabs[1].disabled">Enable / Disable third tab</button>
</p>
<hr />
<uib-tabset active="active">
<uib-tab index="$index" ng-repeat="tab in tabs" heading="{{tab.title}}">
{{tab.content}}
</uib-tab>
</uib-tabset>
<br /><br />
<button ng-click="addTab()">plus</button>
</div>
Any help on this would be nice,
Cheers
You have to use a timeout, uibootstrap doesn't technically support dynamically generated tabs.
$timeout(function() {
$scope.active = $scope.tabs.length - 1;
}, 0);
See this thread.
https://github.com/angular-ui/bootstrap/issues/5656

Angular directive two way databinding fails

I have a dropdown directive with a function which sets the active item in the dropdown:
angular.module('clientApp')
.directive('customDropDown', function ($filter, calculationsFactory) {
return {
templateUrl: 'template/custom-drop-down/custom-drop-down.html',
restrict: 'E',
scope: {
resources: '=',
activeResource: '=',
},
link: function postLink(scope) {
scope.setActiveResource = function(resource){
scope.activeResource = resource;
};
}
};
});
Markup:
<custom-drop-down resources="medias" active-resource="activeMedia"></custom-drop-down>
DirectiveTemplate:
<div class="btn-group" dropdown>
<button type="button" class="btn btn-default dropdown-toggle" dropdown-toggle style="width:100%;" ng-click="$event.stopPropagation()">
{{activeResource.title}} <span class="caret pull-right" style="margin-top:8px;"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li ng-repeat="resource in filtredResources"
ng-click="setActiveResource(resource)"
ng-class="{active: resource === activeResource}">
<a href>{{resource.title}}</a>
</li>
</ul>
</div>
Problem is that the function don't two way bind "activeMedia" in this case. It does not get updated.
I tried to replicate the case in jsfiddle but there it works. Anything I could have missed?
Update
I have identified the issue.
My directive is placed within the accordion directive from ui-bootstrap:
<accordion>
<accordion-group heading="Resources" is-open="true">
<custom-drop-down resources="medias" active-resource="activeMedia"></custom-drop-down>
</accordion-group>
</accordion>
If I move my directive outside the accordion directive, it works. So somehow the accordion directive is interfering with my directive. Possible to solve without modifying the code for ui-bootstrap?
In your case it is a scoping issue, as discussed here.
For elements inside angular-bootstrap controls you need to use $parent. as a prefix on scope variables.
<accordion>
<accordion-group heading="Resources" is-open="true">
<custom-drop-down resources="$parent.medias" active-resource="$parent.activeMedia"></custom-drop-down>
</accordion-group>
</accordion>

How to get form data from ember checkboxes

I have an ember application with two models, user and subject. Each user has a number of subjects associated with them. I have a user/create template in which you can input a new users details, ie their name, email address and associated subjects. The subjects are selected from a list of checkbox values, driven by the subjects in the subject controller. My problem is that when I click on save, the controller seems to skip over the subject selection and doesn't add them to the JSON payload. Can anyone help?
Create Template:
<script type = "text/x-handlebars" id = "user/create">
<div class="modal fade" id="createModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">New User</h4>
</div>
<div class="modal-body">
<div class = "input-group">
<form>
<h5>First Name</h5>
{{input value=firstName}}
<h5>Last Name</h5>
{{input value=lastName}}
<h5>Email</h5>
{{input value=email}}
<h5>Subjects</h5>
{{#each subject in subjects}}
<label>
{{view Ember.Checkbox Binding="id"}}
{{subject.name}}
</label><br />
{{/each}}
</form>
</div>
</div>
<div class="modal-footer">
<a {{action close target="view"}} href="#" class="btn btn-default">Cancel</a>
<a data-dismiss="modal" {{action "save"}} class="btn btn-primary">Save changes</a>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</script>
UserCreateView:
App.UserCreateView = Ember.View.extend({
didInsertElement:function(){
$('#createModal').modal('show');
var self = this;
$('#createModal').on('hidden.bs.modal', function (e) {
self.controller.transitionToRoute("users");
});
},
actions:{
close:function(){
this.$(".close").click();
},
save: function(){
alert('(in view) saved in view');
this.controller.send("save");
self.controller.transitionToRoute("users");
this.$(".close").click();
$('#createModal').modal('hide');
}
},
)};
CreateController:
App.UsersCreateController = Ember.ObjectController.extend({
subjects: function() {
return this.store.find('subject');
}.property(),
actions: {
save: function(){
alert('(UsersCreateController) SENDING A POST REQUEST');
var newUser = this.store.createRecord('user', this.get('model'));
console.log("newUser", newUser);
newUser.save();
this.transitionToRoute('users');
$('#createModal').modal('hide');
}
}
});
The first thing I would look at is the binding attribute you are using on your checkbox(es). For non-checkbox or {{input}} you bind via the value attribute. BUT - for checkboxes you must bind on the "checked" attribute.
Take a look at http://emberjs.com/guides/templates/input-helpers/ - about halfway down under Checkboxes for more info, it will show the accepted attributes, etc.
I experienced the same issue wherein this:
{{input type="checkbox" class="input-small" id="inputCache" value=cache}}
did not work with regard to passing in the checkbox-values to the action handling the submit (other values were passed in and persisted fine), whereas simply changing the attribute to this:
{{input type="checkbox" class="input-small" id="inputCache" checked=cache}}
solved the entire problem.
Hopefully this will do the trick. Good luck :-)

Resources