How to create a closeable tab in angularjs UI-Bootstrap - angularjs

I want to create closeable tabs (like chrome tab or firefox tab, which has a small "x" on every tab). How to configure the ready-made tab component in UI-Bootstrap to add this functionality?
Thanks.

you can use html & ng-click in your tab-heading, e.g.
<div ng-controller="mainCtrl">
<tabset>
<tab ng-repeat="t in tabs">
<tab-heading>{{t.title}} <a ng-click="removeTab($index)" href=''><i class="icon-remove"></i></a></tab-heading>
<div ng-bind-html-unsafe='t.content'></div>
</tab>
</tabset>
</div>
angular.module('myApp', ['ui.bootstrap']).controller("mainCtrl", function ($scope) {
$scope.tabs = [{
title: "one",
content: '<h1>tab one</h1>'
}, {
title: "two",
content: '<h1>tab two</h1>'
}, {
title: "three",
content: '<h1>tab three</h1>'
}];
$scope.removeTab = function (index) {
$scope.tabs.splice(index, 1);
};
});
JSFiddle: http://jsfiddle.net/alfrescian/ZE9cE/

Related

Angularjs strap tab inside tab

I am trying to implement tab inside tab view in AngularJS by using angularstrap 2.1.0.
There are n main tab like "Tab1", "Tab2", "Tab3", ..."Tabn" and each tab can have m subtabs like "Subtab1", "Subtab2", ..."Subtabm".
HTML
<div ng-controller="myController">
<div bs-active-pane="activeTab" bs-tabs="true">
<div ng-repeat="tab in tabs" data-title="{{ tab.title }}" bs-pane="true">
<div>Hello, tab : {{tab.title}}</div>
<div bs-active-pane="tab.activeSubTab" bs-tabs="true">
<div ng-repeat="subTab in tab.subtabs" data-title="{{ subTab.title }}" bs-pane="true">
</div>
</div>
</div>
</div>
</div>
JS
var app = angular.module('myApp', ['mgcrea.ngStrap']);
app.controller('myController', ['$scope', function(scope) {
scope.tabs = [{
title: 'Home',
}, {
title: 'Profile',
}, {
title: 'About',
}];
scope.activeTab = 0;
for (var index in scope.tabs) {
var subtabs = [{
title: 'sub1',
}, {
title: 'sub2',
}, {
title: 'sub3',
}];
scope.tabs[index].subtabs = subtabs;
scope.tabs[index].activeSubTab = 0;
}
}]);
JsFiddle
I tried to implement but it is giving error
Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: $pane in $panes, Duplicate key: object:01E
Does angularstrap tab support this kind of view? If not how should I implement this?

AngularJS ui-bootstrap accordion cannot access variable outside accordion in filtered ng-repeat

I am using AngularJS UI Bootstrap's accordion. I am using ng-repeat with filter inside the accordion. Now the problem is that I cannot access the filtered variable outside <accordion>. If I ditch the accordion and use simple HTML it works fine.
<div ng-app="myApp">
<div ng-controller="AccordionCtrl">
<div>outside accordion{{filteredCampaigns}}</div>
<input type="text" ng-model="q" placeholder="filter" />
<accordion class="accordion" close-others="true">
<div>inside accordion{{filteredCampaigns}}</div>
<accordion-group ng-repeat="campaign in filteredCampaigns=(campaigns | filter:q)">
<accordion-heading>
<h3>{{campaign.title}}</h3>
</accordion-heading>
<p>{{campaign.content}}</p>
</accordion-group>
</accordion>
</div>
</div>
<script>
var app = angular.module('myApp', ['ui.bootstrap']);
app.controller('AccordionCtrl', ['$scope',
function ($scope) {
$scope.campaigns = [{
title: "Test1",
content: "file1.html"
}, {
title: "Test2",
content: "file2.html"
}, {
title: "Test3",
content: "file3.html"
}];
}]);
</script>
I have also created the fiddle here
This is becuase the sub-directives comes with angular-ui have child scopes that does not reflect this new filteredCampaigns variable to the controller's scope.
1st option - Hack it,
1) define an object to contain the filteredCampaigns dynamic variable
$scope.context = {};
2) change your accordion-group to:
<accordion-group ng-repeat="campaign in context.filteredCampaigns=(campaigns | filter:q)">
http://jsfiddle.net/Lryuvm9m/1/
<script>
var app = angular.module('myApp', ['ui.bootstrap']);
app.controller('AccordionCtrl', ['$scope',
function ($scope) {
$scope.context = {};
$scope.campaigns = [{
title: "Test1",
content: "file1.html"
}, {
title: "Test2",
content: "file2.html"
}, {
title: "Test3",
content: "file3.html"
}];
}]);
</script>
<div ng-app="myApp">
<div ng-controller="AccordionCtrl">
<div>outside accordion {{context.filteredCampaigns}} </div>
<input type="text" ng-model="q" placeholder="filter" />
<accordion class="accordion" close-others="true">
<div>inside accordion{{context.filteredCampaigns}}</div>
<accordion-group ng-repeat="campaign in context.filteredCampaigns=(campaigns | filter:q)">
<accordion-heading>
<h3>{{campaign.title}}</h3>
</accordion-heading>
<p>{{campaign.content}}</p>
</accordion-group>
</accordion>
</div>
</div>
2nd option - use Controller as,
i would recommend using Controller as since it will give you more controll of what's defined on the controller's scope and what's not
http://jsfiddle.net/gntt6h5b/
<script>
var app = angular.module('myApp', ['ui.bootstrap']);
app.controller('AccordionCtrl', ['$scope',
function () {
var vm = this;
vm.campaigns = [{
title: "Test1",
content: "file1.html"
}, {
title: "Test2",
content: "file2.html"
}, {
title: "Test3",
content: "file3.html"
}];
}]);
</script>
<div ng-app="myApp">
<div ng-controller="AccordionCtrl as vm">
<div>outside accordion {{vm.filteredCampaigns}} </div>
<input type="text" ng-model="q" placeholder="filter" />
<accordion class="accordion" close-others="true">
<div>inside accordion{{vm.filteredCampaigns}}</div>
<accordion-group ng-repeat="campaign in vm.filteredCampaigns=(vm.campaigns | filter:q)">
<accordion-heading>
<h3>{{campaign.title}}</h3>
</accordion-heading>
<p>{{campaign.content}}</p>
</accordion-group>
</accordion>
</div>
</div>
<accordion> creates an isolated scope and the filteredCampaigns are only available in that scope, not in the parent scope. To add it to the parent scope, you use $parent:
ng-repeat="campaign in $parent.filteredCampaigns=(campaigns | filter:q)">
Another solution would be creating an creating an object an object in the parent scope with a parameter for the filteredCampaings:
// AccordionCtrl
$scope.filteredValues = {
filteredCampaings: []
};
ng-repeat="campaign in filteredValues.filteredCampaigns=(campaigns | filter:q)"
Since you're using it outside of the ng-repeat, you can't see that variable as ng-repeat creates its own scope.
You can use the controller and use the filter manually to retrieve the filtered objects:
$scope.getFilteredCampaings = function () {
$scope.filteredCampaigns = $filter('filter')($scope.campaigns, $scope.q);
return $scope.filteredCampaigns;
}
Fiddle

angularjs - ng-show not working with ng-repeat

I have a variable set to true in ng-click but the div underneath is not displaying. I've followed this post but it looks like it doesnt work in maybe ng-repeat? Here's the plunker: http://plnkr.co/edit/90G1KAx9Fmf2SgRs5gYK?p=preview
angular.module('myAppApp', [])
.controller('MainCtrl', function ($scope) {
$scope.notes = [{
id: 1,
label: 'First Note',
done: false,
someRandom: 31431
}, {
id: 2,
label: 'Second Note',
done: false
}, {
id: 3,
label: 'Finished Third Note',
done: true
}];
$scope.reach= function (id) {
//the assignment below works
//$scope.flag = true;
alert("hello there");
};
});
<div ng-app="myAppApp">
<div ng-controller="MainCtrl">
<div ng-repeat="note in notes">
{{note.id}} - {{note.label}} -
click me
</div>
<div class="row" id="" ng-show="flag">I'm Here</div>
</div>
</div>
It should be ng-click="$parent.flag = true;reach(111);"
click me
Outside ng-repeat
You question is unclear, you could use ng-repeat inside ng-repeat, by maintaining variable in ng-repeat parent scope. and access parent scope using $parent. annotation inside ng-repeat
<div ng-repeat="note in notes">
{{note.id}} - {{note.label}} -
click me
<div class="row" id="" ng-show="$parent.selected == note.id">I'm Here</div>
</div>
</div>
Inside ng-repeat
I would advise you to use ng-init
<div ng-repeat="note in notes" ng-init="parent=$parent">
and after that
click me
Please see demo below
angular.module('myAppApp', [])
.controller('MainCtrl', function($scope) {
$scope.notes = [{
id: 1,
label: 'First Note',
done: false,
someRandom: 31431
}, {
id: 2,
label: 'Second Note',
done: false
}, {
id: 3,
label: 'Finished Third Note',
done: true
}];
$scope.reach = function(id) {
//$scope.flag = true;
alert("hello there");
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body>
<div ng-app="myAppApp">
<div ng-controller="MainCtrl">
<div ng-repeat="note in notes" ng-init="parent=$parent">
{{note.id}} - {{note.label}} -
click me
</div>
<div class="row" id="" ng-show="flag">I'm Here</div>
</div>
</div>
</body>

what happens to scope property if two controllers that apply to one html element define it on scope

I have the following HTML:
<div ng-controller="MainController">
<div class="words">
<span ng-repeat="word in words" ng-click="setActiveWord(word)"> {{word.name}}</span>
</div>
<tabset>
<tab ng-repeat="tab in tabs" heading="{{tab.title}}" active="tab.active" disabled="tab.disabled">
{{activeWord.name}}
</tab>
</tabset>
</div>
Then I have a definition for the MainController which adds tabs property to the scope:
.controller('MainController', ['$scope', function($scope) {
$scope.setActiveWord = function(word) {
$scope.tabs[0].active = true;
}
$scope.tabs = [
{ title:'Dynamic Title 1', content:'Dynamic content 1' },
{ title:'Dynamic Title 2', content:'Dynamic content 2' }
];
}]);
Then tabset directive from here also introduces its own controller TabsetController which also defines the tabs property on the scope:
.controller('TabsetController', ['$scope', function TabsetCtrl($scope) {
var ctrl = this,
tabs = ctrl.tabs = $scope.tabs = [];
Which contoller's tabs property will be used for the element?
Please see this Plunker for complete example.

Tab is not shown after tab's disabled and active property are set to true. Angularjs Tabs

I am working w/ Angularjs.
i am using Tabs and accordion directives.
When tab's disabled and active properties are set to true, tab's content is not showing up.
Here is my plunker snippet that reproduces the issue. Click on PL item and click on Mode 1. The Mode tab will become active and but not shown.
I have a gut feeling it is due to ng-include but do not see why ...
Index.html
<div ng-controller="LeftPaneCtrl">
<tabset>
<tab ng-repeat="tab in leftPane.tabs" heading="{{tab.title}}" active="tab.active" disabled="tab.disabled">
<div ng-include="tab.content"></div>
</tab>
</tabset>
</div>
</body>
Modules.Html:
<accordion close-others="true">
<accordion-group heading="{{module.displayName}}" ng-repeat="module in leftPane.modules">
<div ng-repeat="mode in module.modes" >
<a style="color: green" ng-click="leftPane.selectMode(module, mode)">{{mode.title}} </a>
</div>
</accordion-group>
</accordion>
Srcipt.js:
function LeftPaneModel() {
this.tabs = [
{ title: "Modules", content: "Modules.html", active: true},
{ title: "Modes", content: "Modes.html", disabled: true, active: false },
{ title: "Reports", content: "Reports.html", disabled: true, active: false }
];
this.modulesTab = this.tabs[0];
this.modesTab = this.tabs[1];
this.reportsTab = this.tabs[2];
this.modules = [];
this.modules.push({displayName:'PL',modes:[{title:'Mode 1',id:'Mode1'},{title:'Mode 2',id:'Mode2'}]})
this.selectMode = function(module, mode) {
var tab = this.modesTab;
tab.title = mode.title;
tab.active = true;
tab.disabled = false;
};
}
var emsApp = angular.module('EmsWeb', ['ui.bootstrap']);
emsApp.controller('LeftPaneCtrl', ['$scope',function($scope) {
$scope.leftPane = new LeftPaneModel();
}]);
Any ideas are appreciated.
I posted as an issue w/ angular-ui team. They fixed the issue and should be in next release.
Here is the link to the thread.

Resources