I'm making a little app which sorts websites by groups - where the groups appear as tabs in the tabbable navigator (twitter bootstrap). The premise is therefore, for a new tab to appear whenever you add a new group. This is what it looks like at the moment:
So the part where the new groups show up works perfectly (rendering them by using ng-repeat and going through all of the groups). However, when I click on them, the tabs don't show, i.e. nothing happenes. It worked when I had static tabs.
Here's the relevant html code:
<div class="tabbable tabs-left">
<ul class="nav nav-tabs" id="myTab">
<li class="active">All websites</li>
<li ng-repeat="group in listGroups()">{{group.name}}</li>
<li>+Add group</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="home">
<table class="table">
<tr class="row">
<th align="center">URL</th>
<th align="center" colspan="2">Actions</th>
</tr>
<tr class="row" ng-repeat="item in listSites()">
<td><font color="{{item.color}}">{{item.url}}</font></td>
<td>Edit</td>
<td>Delete</td>
</tr>
</table>
</div>
<div class="tab-pane" id="Social">asdf</div>
<div class="tab-pane" ng-repeat="group in listGroups()" id="{{group.name}}">asdf</div>
</div>
<script>
$('#myTab a').click(function (e) {
e.preventDefault();
$(this).tab('show');
})
</script>
And here's my controller code:
app.factory('groups', function() {
var groups = [];
var groupsService = {};
groupsService.add = function(i_group) {
var group = {"name": i_group}
groups.push(group);
};
groupsService.list = function() {
return groups;
};
return groupsService;
});
function listCtrl($scope,sites, groups) {
$scope.listSites = sites.list;
$scope.listGroups = groups.list;
}
To sum it up, the question is essentially - how do I link tabs that have been dynamically generated to their also dynamically generated content?
You are mixing jQuery code and Angular and that causes problems.
For one, the jQuery code binds to <a>s already existing when the script is executed; new ones (the ones that Angular creates that is) will not get the event handler. You would want something like:
$("#myTab").on("click", "a", function(e) {
// same as your code
});
But you are still mixing Angular/jQuery. And it will probably not work, or work funkilly, because $scope.$apply() doesn't get called. Better is to use ng-click in your tabs and handle the event in the controller:
<li ng-repeat="group in listGroups()">
<a ng-click="selectGroup(group)">{{group.name}}</a>
</li>
(You will have to add the selectGroup() method in the controller.)
Having said that, you'd better use an existing component library, e.g. Angular UI with Bootstrap, as commented by pkozlowski.opensource.
Related
My HTML page using css materialize tabs.
I build all my google chart graphs in 'show' table divs, after it I 'hide' them and when the user click on tab I replace the html tab with the correct one from the 'hide' divs.
In google chrome and firefox it works good, but in IE it doesn't work :(
<div id="row1">
<br />
<table align="center" style="background-color:white">
<tr valign="top">
...
</tr>
<tr valign="top">
...
</tr>
</table>
<br />
</div>
<div id="row2">
<br />
<table align="center" style="background-color:white;">
<tr valign="top">
...
</tr>
<tr valign="top">
...
</tr>
</table>
<br />
</div>
<div class="col s12" id="dashboardtabs">
<ul class="tabs" style="background-color:#80CBC4" id="tabs">
<li class="tab col s3"><a id="titletab1" class="white-text" href="#tab1" onclick="reloadForTabs('titletab1')" style="background-color:#009688">Subjects Status</a></li>
<li class="tab col s3"><a id="titletab2" href="#tab2" class="white-text" onclick="reloadForTabs('titletab2')" style="background-color:#80CBC4">Stratification</a></li>
</ul>
</div>
<div id="tab1" class="col s12"></div>
<div id="tab2" class="col s12"></div>
My js Code:
at the first load change all the rows div to show - google charts need to build on show divs for support user settings (width, high and etc.):
var emptyTabs = function()
{
titletabs.forEach(function (val) {
$('#tab' + val.slice(-1)).html('');
});
}
emptyTabs();
//Changed chart divs from hide to show
titletabs.forEach(function (val) {
$('#row' + val.slice(-1))[0].style.display = 'block';
});
After the user selected tab:
//Changed chart divs from show to hide
titletabs.forEach(function (val) {
$('#row' + val.slice(-1))[0].style.display = 'none';
});
//Display the selected tab (After filters, in the first load and etc.)
var selectedtab = document.getElementsByClassName('white-text active')[0].id;
$('#tab' + selectedtab.slice(-1)).html($('#row' + selectedtab.slice(-1)).html());
In IE the graphs in the 'hide' divs (not in tabs) display correctly, but when the html div insert into the tab - the data is empty, The graph displays with all its properties but without data (bar chart - without the bars).
like this:
And not like this:
Open https://jsfiddle.net/wjqwd467/ in google chrome and in IE and see the different...
Could someone help me?
Thanks!
for starters, Object.values isn't compatible with IE
see --> Object.values() - browser compatibility
try replacing with...
for (var i = 0; i < arraydata.length; i++) {
var daraarr = [];
for (var key in arraydata[i]) {
if (arraydata[i].hasOwnProperty(key)) {
daraarr.push(arraydata[i][key]);
}
}
daraarr.push("color:" + mycolor[arraydata[i].rownum]);
datatable.addRow(daraarr);
}
I have a page with two div panels, a left and a right. Both panels are tabbed using jquery-2.1.4.min.js and jquery-ui.js. One panel has three tabs, and it works.
The js in the head of my page looks like this:
$(function(){
// Doesn't matter if following two lines are reversed. Same output.
$( "#property-card" ).show().tabs(); // this one doesn't work
$( "#tabs" ).show().tabs(); // this one works
});
The html looks like this:
//This tabbed content works:
<div id="tabs">
<ul>
<li>Tasks</li>
<li>Notes</li>
<li>Photos</li>
</ul>
<div id="tabs-1">
<!-- Tasks -->
</div>
<div id="tabs-2">
<!-- Notes -->
</div>
<div id="tabs-3">
<!-- Other -->
</div>
The other div panel looks something like this:
//This one shows hyperlinked text within the content area, instead of showing tabs
<div id="property-card" class="eight columns light-manilla curved10 border-dark border-2 border-ridge padding-1-percent">
<ul>
<li>Property</li>
<li>Help</li>
<li>List Price</li>
<li>Taxes</li>
<li>HOA</li>
<li>Showing Instructions</li>
<li>BPO Values</li>
<li>Buyer Leads</li>
</ul>
<div id="property">
</div>
<div id="property-help">
</div>
<div id="property-list-price">
</div>
<div id="property-taxes">
</div>
<div id="property-hoa">
</div>
<div id="property-showing-instructions">
</div>
<div id="property-bpo-values">
</div>
<div id="property-buyer-leads">
</div>
</div>
(not sure if this is related) Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help http://xhr.spec.whatwg.org/jquery-2.1.4.min.js:4:14346
ReferenceError: data is not defined
(I think this one is related) jquery-2.1.4.min.js%20line%202%20%3E%20eval:35:1
See inline screen shot sample for example of what's going on.
Hate answering my own questions, but in another file at the bottom of my html, there is another javascript block, which "activated" the working tabbed div, but because I didn't add the new tabbed div (because I didn't realize that second javascript block was there) the second tabbed div didn't work. Here is what made it work:
$(function () {
$('#property-card').tabs({
activate: function (event, ui) {
var $activeTab1 = $('#property-card').tabs('option', 'active');
}
});
$('#tabs').tabs({
activate: function (event, ui) {
var $activeTab2 = $('#tabs').tabs('option', 'active');
if ($activeTab2 == 2) {
// HERE YOU CAN ADD CODE TO RUN WHEN THE SECOND TAB HAS BEEN CLICKED
$("#mls-images-carousel").css("display","block");
retrieveAssetImages('<?php echo $as_id; ?>');
}
else{
$("#mls-images-carousel").css("display","hidden");
}
}
});
});
I have an mvc project where I have implemented two jQuery selectable plugin like below:
The <HTML> code,
<div class="product-page-options">
<div class="pull-left">
<label class="control-label" style="font-weight:bolder">Size:</label>
<ol class="ui-selectable" style="width:auto" id="selectable">
#{
var size = Model.AvailableSizes.Split(',');
foreach (var item in size)
{
<li class="ui-selectable">#item</li>
}
}
</ol>
</div>
<div class="pull-left">
<label class="control-label">Color:</label>
<ol class="ui-selectable" style="width:auto" id="selectable1">
#{
var color = Model.AvailableColors.Split(',');
foreach (var clr in color)
{
<li class="ui-selectable">#clr</li>
}
}
</ol>
</div>
</div>
The static script for selectable jQuery plugin.
<script type="text/javascript">
$(document).ready(function () {
$("#selectable").selectable({
selected: function (event, ui) {
$(ui.selected).siblings().removeClass("ui-selected");
$("#selectedsize").val($("li.ui-selected").html());
}
});
});
</script>
<script type="text/javascript">
$(document).ready(function () {
$("#selectable1").selectable({
selected: function (event, ci) {
$(ci.selected).siblings().removeClass("ui-selected");
$("#selectedsize").val($("li.ui-selected").html());
}
});
});
</script>
The first selectable jQuery plugin works perfectly while the second is not functioning properly. I mean I cannot select any item from the second selectable list and also the appearance is not same as the first one. The picture below shows clearly the problem.
Anything i can do about it? any help would be appreciated. Thanks in advance.
There's 2 issues at play here. Firstly, you will need to have styles set up specifically for both of the selectables (if you have based your code on the examples on the jQuery UI site. Secondly, upon selecting in the selector for the items, you will need to identify the path to the selected li element as a child of the relevant selectable.
$("#selectedcolor").val($("#selectable1>li.ui-selected").html());
The following plunker will show you it working :
Link To My Plunker
Related to a previous post, I am really stuck on user click updating an object array in my angular app. In reality, the user click will force an http get. In the sample code here, I have simplified to a hard coded array. Also, the real app has multiple tabs, I have cut down the code to the crux, which is updating of the object on a click messing up the view. For example, the table in the view loses the selectable column. Other bad stuff happens in real app. I suspect some data binding issue?
<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header mdl-layout--fixed-tabs">
<header class="mdl-layout__header">
<div class="mdl-layout__tab-bar mdl-js-ripple-effect">
Assets
<div class="mdl-layout-spacer"></div>
</div>
</header>
<main class="mdl-layout__content">
<section class="mdl-layout__tab-panel is-active" id="fixed-tab-1">
<div class="page-content">
<div class="table-content mdl-grid">
<div class="mdl-cell mdl-cell--6-col">
<table id=table1
class="table-fullwidth mdl-data-table mdl-data-table--selectable mdl-js-data-table mdl-shadow--4dp" >
<thead>
<tr>
<th class="mdl-data-table__cell--non-numeric"><span class="table-header">Asset</span></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="x in restdata">
<td class="mdl-data-table__cell--non-numeric mdl-typography--thin">{{ x.asset }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</section>
</main>
</div>
My simple js is like this:
var app = angular.module('homeApp.protect', []);
app.controller('protectCtrl', ['$scope', function($scope) {
$scope.tabcount = 0;
$scope.restdata = [];
$scope.response = [ {"id":"1","asset":"V-1-A1"},
{"id":"2","asset":"V-2-A1"},
{"id":"3","asset":"V-1-A2"},
{"id":"4","asset":"V-2-A2"}];
// activate tabs entered by user
$scope.activateTab = function (tabId) {
$scope.tabcount++;
console.log("In activate tab " + tabId + " tabcount = " + $scope.tabcount);
// get lists of all assets for all agents
if (tabId == "Assets") {
angular.copy($scope.response, $scope.restdata);
console.log($scope.restdata);
};
};
//Default entry on page load
$scope.activateTab ("Assets")
}]);
On initial load, the selectable check boxes look fine. On subsequent tab clicks, they disappear from rows (appear in header only). I have seen other problem with dynamic data. 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"/>