"Previous" / "Next" tab navigation system (AngularJS / AngularJS Material) - angularjs

I am developing some content display in various tabs, using Angular.js 1.5.x and AngularJS Material 1.1.0.
I first used the Angular Material md-tabs system like this : https://material.angularjs.org/latest/demo/tabs.
Unfortunately, our users do not use them as they do not seem to understand they are tabs. I am now working on a new, more obvious, tabs system :
I haven't found any Angular material way to create this "previous/next"-based tab navigation system.
Do you know where I could look ? It does not need to be Angular Material, any help or lead is welcome :) I want to avoid complexity or custom code if possible, so I want to capitalize on existing frameworks.

You can still use mdTabs. You can create a custom button and make them to command the tab by changing the selected tab with: md-selected
Then hide the tab navigation by md-no-pagination , or by adding display:none to .md-tab css.
eg, for 3 tabs:
<div>
<md-tabs md-selected="tabIndex">
<md-tab label="tab1">
tab1 content
</md-tab>
<md-tab label="tab2">
tab 2 content
</md-tab>
<md-tab label="tab3">
tab 3 content
</md-tab>
</md-tabs>
<md-button ng-click="back()" class="md-raised">
Previous
</md-button>
<md-button ng-click="next()" class="md-raised">
Next
</md-button>
</div>
and controller:
$scope.back = function() {
if ($scope.tabIndex > 0) {
$scope.tabIndex--;
}
};
$scope.next = function() {
if ($scope.tabIndex < 2) {
$scope.tabIndex++;
}
}
plunkr: http://plnkr.co/edit/NWSRBb?p=preview

Related

changing md-selected with md-tabs and using md-button (prev, next)

I am experiencing a strange behavior when switching tabs using different methods of changing the tab index. I can change md-selected using the $scope.changeQuestion function with ng-click. I can also use the built in clicking of the md-tab to change md-selected. The issue lies when I click the md-tab and then try to click my prev or next buttons that utilize the $scope.changeQuestion function. If I click the tabs and then try to use my buttons to change the index, the buttons don't change the tab index anymore. They do log the appropriate index I want to switch to, however.
controller
$scope.changeQuestion = function(index){
$scope.selectedQuestion = index;
};
html
<md-tabs md-selected='selectedQuestion' md-stretch-tabs md-dynamic-height md-border-bottom>
<md-tab ng-repeat='question in assessment.questions | toArrayKeepKeys | orderBy: "order"'>
<md-tab-label>
{{question.order}} <i class="fas fa-fire fire" ng-if='question.bonus'></i>
</md-tab-label>
<md-tab-body>
<div class='question-tab-content'>
<question class='margin-top-1em' details='question' answer='answers[question.key]'></question>
<div>
<md-button ng-click='changeQuestion($index - 1)' ng-hide='question.order === 1' class='md-primary md-raised no-left-margin'>Previous</md-button>
<md-button ng-click='changeQuestion($index + 1)' ng-hide='question.order === _.size(assessment.questions)' class='md-primary md-raised no-left-margin'>Next</md-button>
</div>
</div>
</md-tab-body>
</md-tab>
</md-tabs>
Here is the example of the behavior:
I was able to get a working example in codepen but can't seem to get it to work in my project.
Update
Tried putting a $watch on $scope.selectedQuestion and it doesn't fire if I click the tabs. It's like the md-selected='selectedQuestion' and $scope.selectedQuestion are different but only after I click a tab.
Found Solution: scope inheritance
Changing $scope.selectedQuestion = 0; to $scope.selectedQuestion = { selected: 0 }; and updating other references did the trick.
Unexplained: why the codepen example works without the modifications from the solution

Load and call content of md-tab when it's clicked or selected from md-tabs (angular 1.5)

I'm using following HTML structure in parent.html page (and have corresponding Controller for this parent HTML Page)
<md-tabs md-dynamic-height class="report-tabs" layout-align="center stretch" md-no-pagination="true">
<md-tab>
<md-tab-label>
<span class="tab-label">Tab 1</span>
</md-tab-label>
<md-tab-body>
<div ng-include="tab1-page-URL"></div>
</md-tab-body>
</md-tab>
<md-tab>
<md-tab-label>
<span class="tab-label">Tab 2</span>
</md-tab-label>
<md-tab-body>
<div ng-include="tab2-page-URL"></div>
</md-tab-body>
</md-tab>
Currently when I load this parent.html page, All contents of all tabs are getting loaded at beginning.
Don't we have lazy loading where contents of tab are loaded when it's active (when selected/clicked upon) ?
If we don't have such provision, How can I call function of child tab's controller, when particular tab is selected ? Currently all functions of all child tab's controllers are getting called - which is time consuming and not needed where user will see first tab only when page completes compiling and rendering ?
I've tried calling Child-tab controller functions on parent.html page, but unless all md-tab contents are not loaded, nothing from child-controller is accessible. Only accessible part in this page will be parent.html's own controller functions.
Let me know if any other way I can proceed, Or am I missing completely something here ? Thank you.
From the official doc, for using md-tab , there are no lazy loading contents.
If we don't have such provision, How can I call function of child
tab's controller, when particular tab is selected ? Currently all
functions of all child tab's controllers are getting called - which is
time consuming and not needed where user will see first tab only when
page completes compiling and rendering ?
My method is by using the button only tabs, then using dynamic ng-include, and setting the reladed view during selecting the tab, by md-on-select
something like:
<md-tabs>
<md-tab label="Tab #1" md-on-select="onTabSelected(1)"></md-tab>
<md-tab label="Tab #2" md-on-select="onTabSelected(2)"></md-tab>
<md-tab label="Tab #3" md-on-select="onTabSelected(3)"></md-tab>
</md-tabs>
<md-content class="md-padding">
<ng-include src="'templates/tabs/'+ tabId +'.html'"></ng-include>
</md-content>
controller :
$scope.tabId = 1; //default template loaded
$scope.onTabSelected = function(tabId) {
//you can add some loading before rendering
$scope.tabId = tabId;
};
templates directory:
templates/
tabs/
1.html
2.html
3.html
You could try something like:
<md-tabs md-dynamic-height class="report-tabs" layout-align="center stretch" md-no-pagination="true">
<md-tab md-on-select="onSelect(tab)" ng-repeat="tab in tabs">
<md-tab-label>
<span class="{{tab.class}}">{{tab.label}}</span>
</md-tab-label>
<md-tab-body>
<div ng-if="selectedTab === tab.id" ng-include="{{tab.url}}"></div>
</md-tab-body>
</md-tab>
and in controller:
$scope.tabs = [
{id: 1, label: "label for tab 1", url: "url-tab-1.html"},
{id: 2, label: "label for tab 2", url: "url-tab-2.html"}
];
$scope.onSelect = function(tab) {
$scope.selectedTab = tab.id;
};
$scope.onSelect(1);

Best way to implement a toggle button in AngularJS Material

I am looking for a simple solution to implement a toggle button with a custom selected / unselected icon in AngularJS Material.
The functionality should be identical to the md-checkbox (with ng-model for the selection state), but I want to have my own icon displayed for selected / unselected state. md-checkbox does not seem to support custom icons, and md-button lacks the ng-model.
Preferably I would like to avoid implementing a custom directive and only make this work through css. Is this possible with AngularJS Material?
You can define a toggle function to create toggle activity in your controller, like this:
$scope.toggle = function() {
$scope.variable = !$scope.variable
console.log($scope.variable);
}
Button on the html:
<md-button
ng-click="toggle()"
ng-class="{'active': variable, 'disable': !variable}">
After some digging the best solution currently seems to be using an md-button, which allows custom icons, and extending it with ng-click and ng-class like this:
<md-button ng-click="selected = !selected"
ng-class="{'selected-button' : selected}">
This takes care of the selection state. And in CSS I can then set the styles for the selected-button class
Even though the solution is rather simple, I think there should be an out-of-the-box support from Angular Material for a toggle button (or checkbox) with custom icons.
Properly using all classes of Angular Material v1.x
<md-button class="md-icon-button"
ng-click="filterToggle = !filterToggle"
ng-class="{'md-primary md-raised' : filterToggle}">
<md-tooltip md-direction="bottom">Filter</md-tooltip>
<md-icon ng-hide="filterToggle">filter_list</md-icon>
<md-icon ng-show="filterToggle">clear_all</md-icon>
</md-button>
in controller set
$scope.filterToggle = false;
var app = angular.module('app', []);
app.controller('CommentController', function($scope) {
$scope.filterToggle = true;
//start function.
$scope.StartFunc = function() {
$scope.filterToggle = false;
console.log('in pause function.');
};
$scope.CallFunc = function() {
$scope.filterToggle ? $scope.StartFunc() : $scope.PauseFunc();
}
// pause function.
$scope.PauseFunc = function() {
$scope.filterToggle = true;
console.log('in pause function.');
}
})
<link href="https://material.angularjs.org/1.1.2/angular-material.min.css" rel="stylesheet" />
<script src="https://material.angularjs.org/1.1.2/angular-material.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="CommentController">
<md-input-container>
<md-button class="md-icon-button md-primary md-raised" ng-click="CallFunc()">
<md-tooltip md-direction="bottom">Start/Pause Func</md-tooltip>
<md-icon ng-hide="filterToggle" style="background-color:grey;width:auto;">pause</md-icon>
<md-icon ng-show="filterToggle" style="background-color:grey;width:auto;">play_arrow</md-icon>
</md-button>
</md-input-container>
</div>
</div>

AngularMaterial Tabs showing only 1st tab

Why are md-tabs showing only the first tab? The rest of them appears after I click in the tabs area.
First tab looks like this:
After clicking in the tab area:
My code looks like this:
<md-tabs md-dynamic-height md-border-bottom>
<md-tab label="Home"></md-tab>
<md-tab label="Profile"></md-tab>
<md-tab label="Messages"></md-tab>
</md-tabs>
On purpose I left the content of tabs empty because I want to get rid of the transition animation as described here.
One of the problems could be that the tabs are in bootstrap dropdown menu.
Thank you for your ideas!
EDIT
I have just found out that the tabs has troubles even without bootstrap when using them in md-menu.
Have you solved it yet?
I'm having the same problem except that my angular tabs is in bootstrap's modal.
When I click on a button to toggle the modal it only show the first tab until I click on it.
After doing some testing it appears that I could work around by hiding the angular tabs with ng-show and show it after a small amount of delay.
<button ng-click="controller.showTabs()">Show Tab</button>
<md-tabs md-dynamic-height md-border-bottom ng-show="show_tab">
<md-tab label="Home"></md-tab>
<md-tab label="Profile"></md-tab>
<md-tab label="Messages"></md-tab>
</md-tabs>
Controller's function when user clicks on the drop down / button to toggle the modal:
this.showTabs =
function()
{
//250ms delay
$timeout(function()
{
$scope.show_tab = true;
},250);
}

titles not showing correctly in angular material tabs

I'm using angular material tabs but there is something wrong with my implementation and it gives me this result (on Chrome and Firefox):
As you can see the tab titles are truncated.
Here is my implementation:
HTML:
<md-tabs>
<md-tab ng-repeat="tab in tabs">
<md-tab-label>{{tab.titre}}</md-tab-label>
<div class="md-tabs-content">
content tab
</div>
</md-tab>
</md-tabs>
JS:
var tabs = [];
for(i=0;i<3; i++){
tabs.push({
titre: 'title'
});
}
$scope.tabs = tabs;
$scope.selectedTab = 0;
Added the plnkr:
http://plnkr.co/edit/nFMFmaGpLUwJPxRd1TpT?p=preview
Quoting from Angularmaterial docs for md-tab
Please note that if you use <md-tab-label>, your content MUST be wrapped in the <md-tab-body> tag. This is to define a clear separation between the tab content and the tab label.
So can you trying changing your code to:
<md-tabs>
<md-tab ng-repeat="tab in tabs">
<md-tab-label>{{tab.titre}}</md-tab-label>
<md-tab-body class="md-padding">
content tab
</md-tab-body>
</md-tab>
</md-tabs>

Resources