I have three buttons on a page and depending on which on you click a different set of tabs is shown. Once you make a selection a reset button is available to clear your choice. In these tabs a user is able to make a selection and is then taken to a results page. What currently happens is, if a user clicks back via the browser the default view is the three original buttons but what I would like is the default view to be the last tab they were in before sending off for results. Is there a clever angular way to handle this?
Example:
http://plnkr.co/edit/2WZ12TKcHGXWmLhgD1vj
Buttons:
<div class="btn-group btn-group-justified" role="group" aria-label="Qualifications">
<div class="btn-group" role="group">
<button type="button" class="btn btn-default" ng-click="tab = 1; showSelectorTabs=true; showSelectorButtons=true">Button 1</button>
</div>
<div class="btn-group" role="group">
<button type="button" class="btn btn-default" ng-click="tab = 2; showSelectorTabs=true; showSelectorButtons=true">Button 2</button>
</div>
<div class="btn-group" role="group">
<button disabled="true" type="button" class="btn btn-default" ng-click="tab = 3; showSelectorTabs=true; showSelectorButtons=true">Button 3</button>
</div>
</div>
Tabs:
<tabset ng-show="tab == 1">
<ul class="nav nav-tabs">
<li role="presentation" class="active">Home
</li>
<li role="presentation">Profile
</li>
<li role="presentation">Messages
</li>
</ul>
</tabset>
<tabset ng-show="tab == 2">
<ul class="nav nav-tabs">
<li role="presentation" class="active">Home
</li>
<li role="presentation">Profile
</li>
<li role="presentation">Messages
</li>
</ul>
</tabset>
<tabset ng-show="tab == 3">
<ul class="nav nav-tabs">
<li role="presentation" class="active">Home
</li>
<li role="presentation">Profile
</li>
<li role="presentation">Messages
</li>
</ul>
</tabset>
</div>
Nicholas is right, but I did something like this recently without using ngRoute so I wanted a simpler way to accomplish it. In addition to your original issue, you might want to consider using ng-repeat because (based on your example), that would save you a lot of code. Like so:
<div class='btn-group' role='group' ng-repeat='button in buttons'>
<button type='button' class='btn btn-default' ng-click='buttonSelected(button)'>Button {{ button }}</button>
</div>
<tabset ng-repeat='tabset in tabsets' ng-show='tabset.name == selectedTabset'>
<ul>
<li ng-repeat='tab in tabset.tabs' ng-class='{active: tab.active}'><a href='#{{ tabset.name }}_{{ tab.name }}'>{{ tab.name }}</a></li>
</ul>
</tabset>
Like MichaelOryl mentioned, I'd also suggest moving some of that logic out of the view and into the controller. I added the scope objects called above in ng-repeat in case you're not already familiar with that.
$scope.buttons = ['One','Two','Three'];
$scope.tabsets = [
{ name: 'One',
active: false,
tabs: [
{name: 'Home', active: true, content: ''},
{name: 'Profile', active: false, content: ''},
{name: 'Messages', active: false, content: ''}]
},{ // two more, same structure as first tabset }]
$scope.showSelectorButtons = true;
$scope.showSelectorTabs = false;
$scope.selectedTabset = 'None';
$scope.buttonSelected = function(selected){
$scope.showSelectorButtons = false;
$scope.showSelectorTabs = true;
$selectedTabset = selected;
}
And finally, here's my take on the location. You'll notice I added unique identifiers to the hrefs in the view, then I use those to select the proper tab on page load. This is also off the cuff, so no promises but it would look something like this:
$scope.deepLink(url){
if(url.indexOf('#') > -1){
var hash = url.split('#')[1];
var tabsetId = hash.split('_')[0];
var tabId = hash.split('_')[1];
var hashTabset = $filter('filter')($scope.tabsets, {name: tabsetId}, true);
var hashTab = $filter('filter')(hashTabset, {name: tabId}, true);
angular.forEach($scope.tabsets, function(tabset){
tabset.active = false;
angular.forEach(tabset.tabs, function(tab){ tab.active = false; });
});
hashTabset.active = true;
hashTab.active = true;
}
}
var url = $location.url();
$scope.deepLink(url);
Hope this is helpful, if you have any questions let me know.
You might want to consider saving the current selected tab in either a cookie or in browser local storage. You would only erase the value when appropriate (such as when the reset button is hit). I believe this would cause the currently selected view to be the default, more or less, when the user comes back in due to hitting page refresh or the back button.
I've use LocalStorageModule with good success for app defaults and general settings.
Otherwise you might want to just use the generic ngCookies module.
You should probably change your ngClicks to call functions inside your controller, though:
ng-click="setTab(3)"
You'd then have something like this as a controller, calling in the localStorageService, for example. This is off-the-cuff code - it probably won't run. I'm just trying to show you what I mean.
app.controller('SecretCtrl', function ($scope, localStorageService) {
$scope.tab = localStorageService('defaultTab');
if ($scope.tab == null) { $scope.tab = 0; }
$scope.setTab = function(tabNumber) {
$scope.tab = tabNumber;
$scope.showSelectorTabs=true;
$scope.showSelectorButtons=true
localStorageService.add('defaultTab', tabNumber);
}
};
This will work if you're using ngRoute or something similar and actually triggering URL changes in your app.
Push the state of $scope.tab into the URL with $location.search(), and when your page first loads read the state of it back off the URL to initialize which tab is active.
Change your buttons to call a function on your controller:
<button type="button" class="btn btn-default" ng-click="showTab(1)">Button 1</button>
Function on your controller does the logic you previously had in the HTML, in addition it updates the URL to contain the current selected tab number:
function showTab(tabNumber) {
$scope.tab = tabNumber;
$scope.showSelectorTabs=true;
$scope.showSelectorButtons=true;
$location.search({tab: tabNumber});
}
When your page is first loaded, initialize the tab from the value in the URL if it's available, otherwise default to tab 1 or whatever you like:
$scope.tab = $location.search().tab != null ? $location.search().tab : 1;
Related
I have a list of Items with different button with them. Plunker
Quick View:
I want something like if I click on any of the buttons, related text will be copy to the div above. Also if I click on the button again it will removed from the Div.Same for each of the buttons. [I added manually one to show how it may display ]
I am not sure how to do that in Angular. Any help will be my life saver.
<div ng-repeat="item in csTagGrp">
<ul>
<li ng-repeat="value in item.csTags">
<div class="pull-left">
<button type="button" ng-class='{active: value.active && !value.old}' class="btn btn-default btn-xs">{{value.keys}}</button>
<span>=</span>
</div>
<div class="pull-left cs-tag-item-list">
<span>{{value.tags}}</span>
</div>
</li>
</ul>
</div>
The simplest thing would be to use $scope.tags object to store selected tags and add/remove them with the scope method similar to this:
$scope.tags = {};
$scope.toggleTag = function(tag) {
if (!$scope.tags[tag]) {
$scope.tags[tag] = true;
}
else {
delete $scope.tags[tag];
}
};
Demo: http://plnkr.co/edit/FrifyCrl0yP0T8l8XO4K?p=info
You can use ng-click to put in your scope the selected value, and then display this value instead of "Win".
http://plnkr.co/edit/IzwZFtRBfSiEcHGicc9l?p=preview
<div class="myboard">
<span>{{selected.tags}}</span>
</div>
...
<button type="button" ng-click="select(value)">{{value.keys}}</button>
I've got a notifications button in a rails app that lists friends' recent activity. It has a count badge that appears over the button. Once a user views those notifications I want to clear the current badge so the count can restart with new notifications. Any suggestions?
var renderActivities = function() {
var source = $('#activities-template').html();
var template = Handlebars.compile(source);
var html = template({
activities: window.loadedActivities,
count: window.loadedActivities.length
});
I was trying something like this:
$('#notifications-button').click(function(event) {
count: = 0;
});
Source code (outside of body):
<script id="activities-template" type="text/x-handlebars-template">
<button class="btn btn-default" class="dropdown-toggle notifications-button" data-toggle="dropdown"><i class="fa fa-bell-o fa-2x"><span class="badge notifications-count">{{count}}</span></i></button>
<ul class="dropdown-menu pull-right notifications-menu">
{{#each activities}}
{{activityLink}}
{{/each}}
<li class="divider"></li>
<li>See All</li>
</ul>
</script>
I'm really not all that familiar with Javascript but really need this feature to work.
You're going to want to grab the selector that contains the count and set the text to 0. Something like so...
$('#notifications-button').on('click', function() {
$('.notifications-count').text('0');
});
I am making a Cordova/Phonegap app using Appframework and Knockout js for front and back end. The issue I am running into is occurring in the header of the firstly loaded panel.
The HTML:
<div id="afui">
<div id="content">
<!--CLASS LIST VIEW -->
<div class="panel" title="Classes" id="classList"
data-footer="none" selected="true">
<header>
<div style="float:right" data-bind="click:addClass"
class="button icon add white"></div>
<h1>Classes</h1>
</header>
<ul class="list" data-bind="foreach: classes">
<li data-bind="click:openClass, attr: { id: id, name: name }">
<a href="#categoryList">
<span style="padding-right:20px" data-bind="text: name">
</span>Grade:
</a>
</li>
</ul>
</div>
<!-- CATEGORY VIEW -->
<div class="panel" id="categoryList" title="Class Name">
<header>
<a id="backButton" href="javascript:;" class="button"
style="visibility: visible; ">Back</a>
<h1 data-bind="text: header "></h1>
<div style="float:right" data-bind="click:addCategory"
class="button icon add white">
</div>
</header>
<ul class="list" data-bind="foreach: categories">
<li data-bind="text:name"></li>
</ul>
</div>
</div>
</div>
So in the first panel of id="classList" the addClass button in the header does not get triggered when clicked, tapped, or any other sort of user interaction.
If I tap on a list item with a link to the panel of id="categoryList" and transition to that panel, the button in the top right of that header with event click:addCategory DOES work.
The only way I can get the addClass click event to fire is when I init my models...
ko.applyBindings(classModel, document.getElementById('classList'));
ko.applyBindings(categoryModel, document.getElementById('categoryList'));
is by not specifying the second parameter for the classModel ko binding. Of course this will be a problem, because I have multiple views and need to specify which container each of my models should observe.
VIEW MODELS
ClassModel:
function classInfo(name, id, parent) {
var self = this;
self.name = ko.observable(name);
self.score = ko.observable('');
self.id = ko.observable(id);
self.openClass = function(data, event) {
parent.currentClass(event.currentTarget.name);
};
}
function classListViewModel() {
var self = this;
//class array object
self.classes = ko.observableArray([]);
//current class name
self.currentClass = ko.observable().publishOn("currentClass");
//remove a class from the model
self.removeClass = function(obj) {
//remove the class
};
//add a new class to the model
self.addClass = function() {
//add a new using classInfo object
};
}
So, what is going on here? Is Appframework doing something weird to the header on the main page causing the click:addClass event to not fire?
Any insight/help would be much appreciate, thanks!
I wanted to view different HTML pages based on what a user clicks. For example, I have three tabs set up as so:
<div class="span7" >
<ul class="nav nav-tabs" style="margin-bottom: 5px;">
<li class="active">First</li>
<li>Second</li>
<li>Third</li>
</ul>
<div class="span12" style="margin-left:0;" ng-grid="gridOptions"></div>
</div>
And I merely want to view a different page based off of what the individual clicks. For example, if he clicks First, he will see First's html page where source.sourceObject in the code below denotes which html page to view. It is written like so:
<div class="span5">
<div class="edus-activity-container">
<div ng-show="sourceViewState.selected" class="edus-admin-activities-grid" />
</div>
<div ng-include="'/partials/' + source.sourceObject + '.html'"/>
</div>
where in my javascript file, source.sourceObject is defined based off of if I click the First, Second or Third tab. However, my implementation is not working. I made sure I had no typos in the spelling of my files in source.sourceObject. Any ideas on how to do so?
In your controller:
var pages = { 'one': 'partials/one.html', 'two':'partials/two.html' }
$scope.currentPage = pages['one'] ; //This is required if you want a default page
$scope.first = function(){ $scope.currentPage = pages['one']; }
$scope.two = function(){ $scope.currentPage = pages['two']; }
In your template/HTML
<div ng-include="currentPage"/>
I have an ng-repeat that repeats a dropdown. Each repeated div that holds the dropdown has a unique ID generated by the controller that I can reference.
How can I pass back the selected option for that specific dropdown? Right now, if one dropdown is selected, the value for selectedParameter.name changes for all dropdowns.
<div id="{{ mergeVar.name }}" class="alert {{ selectedParamClass }}" ng-repeat="mergeVar in mergeVars">
<b>merge value: </b> {{mergeVar.name}}
<div class="dropdown pull-right">
<button type="button" class="btn btn-sm btn-control dropdown-toggle" data-toggle="dropdown">
{{selectedParameter.name || 'Match the Paramater'}}
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li ng-repeat="param in availableParams">
<a ng-click="selectParameter(parampass)">{{param.name}}</a>
</li>
</ul>
</div>
</div>
//controller.js
$scope.selectParameter = function(parampass) {
console.log('parameter selected')
$scope.selectedParameter = parampass
$scope.selectedParamClass = 'alert-success'
}
Do this instead to affect only one instance of your object:
$scope.selectParameter = function(parampass) {
console.log('parameter selected')
parampass.selectedParamClass = 'alert-success';
}
What you need is to add the property to the instance "row" object.
You can still store the selected object:
$scope.selectedParameter = parampass
But based on what I see in your code what you probably want do to is to use the ng-class="selectedParamClass" when an item is selected for the object selected.