Access each individual custom cell with Angular bootstrap calendar - javascript

I'm working on an app where I need a calendar skeleton (without the standard events) so I can put tables inside each cell, so I'm using the Angular Bootstrap Calendar with custom cell templates. I have everything working fine in terms of displaying the custom template in each cell and being able to navigate between months, but I need to be able to access each individual day and make data available in each one.
Here's my controller:
(function() {
angular.module('myApp')
.controller('calendarController', function($scope, $state, moment, calendarConfig) {
var vm = this;
calendarConfig.templates.calendarMonthCell = 'views/calendar/dayTemplate.html';
calendarConfig.dateFormatter = 'moment';
vm.events = [];
vm.calendarView = 'month';
vm.viewDate = moment().startOf('month').toDate();
$scope.$on('$destroy', function() {
calendarConfig.templates.calendarMonthCell = 'mwl/calendarMonthCell.html';
});
});
})();
and the corresponding dayTemplate.html:
<div class="cal-month-day">
<span
class="pull-right"
data-cal-date
ng-click="calendarCtrl.dateClicked(day.date)"
ng-bind="day.label">
</span>
<!--
<small style="position: absolute; bottom: 10px; left: 5px">
There are {{ day.events.length }} events on this day
</small> -->
<!-- <table class="table table-bordered table-condensed"> -->
<table class="table table-bordered table-condensed">
<thead>
<tr>
<td>Station</td>
<td>Position</td>
<td>Name</td>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="3" align="top">1</td>
<td>Position</td>
<td>Name</td>
</tr>
<tr>
<td>Position</td>
<td>Name</td>
</tr>
<tr>
<td>Position</td>
<td>Name</td>
</tr>
</tbody>
</table>
<table class="table table-bordered table-condensed">
<tbody>
<tr>
<td rowspan="3" align="top">2</td>
<td>Position</td>
<td>Name</td>
</tr>
<tr>
<td>Position</td>
<td>Name</td>
</tr>
<tr>
<td>Position</td>
<td>Name</td>
</tr>
</tbody>
</table>
<table class="table table-bordered table-condensed">
<tbody>
<tr>
<td rowspan="3" align="top">3</td>
<td>Position</td>
<td>Name</td>
</tr>
<tr>
<td>Position</td>
<td>Name</td>
</tr>
<tr>
<td>Position</td>
<td>Name</td>
</tr>
</tbody>
</table>
</div>
When using the calendar as it normally is used, you can see that the days.events object has the data, but I need to access that object, or create my own so I can fill my tables. Is there a simple (or even not so simple) way to do that?
Thanks.
UPDATE: I just went back and read the docs and noticed this
An optional expression that is evaluated on each cell generated for
the year and month views. calendarCell can be used in the expression
and is an object containing the current cell data which you can modify
(see the calendarHelper service source code or just console.log it to
see what data is available). If you add the cssClass property it will
be applied to the cell.
Due to my lack of knowledge, I'm not understanding how to use this to override. If I console.log calendarCell in my calendarController it chokes because that object doesn't exist. If I'm reading this correctly, I can intercept the cell data and modify, but I'm not understanding how.

In this case, RTFM turned out to be the correct answer. Per the docs:
<div ng-controller="CellModifierCtrl as vm">
<ng-include src="'calendarControls.html'"></ng-include>
<mwl-calendar
events="vm.events"
view="vm.calendarView"
view-date="vm.viewDate"
cell-modifier="vm.cellModifier(calendarCell)">
</mwl-calendar>
</div>
goes with this in the controller:
vm.cellModifier = function(cell) {
console.log(cell);
if (cell.label % 2 === 1 && cell.inMonth) {
cell.cssClass = 'odd-cell';
}
cell.label = '-' + cell.label + '-';
};
and voila!, you have access to the data. I'm still trying to figure out how to pass additional data into the function, but I'll open a separate question for that.

Related

How to make footable work in a table that's being populated with JS from JSON?

I have something like this:
<table id="thatTable" class="table toggle-circle">
<thead>
<tr>
<th>ID</th>
<th>FieldA</th>
<th data-hide="all">FieldB</th>
<th data-hide="all">FieldC</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan="4">
<div class="text-right">
<ul class="pagination"></ul>
</div>
</td>
</tr>
</tfoot>
</table>
Then a JS like this:
var fillThatTable = function (list) {
$.each(list, function (index, item) {
$('#thatTable tbody').append($('<tr>')
.append($('<td>').text(item.ID))
.append($('<td>').text(item.FieldA))
.append($('<td>').text(item.FieldB))
.append($('<td>').text(item.FieldC))
)
);
});
};
Everything works fine, the table gets the data and shows it all. Problem comes when I want to set footable() to that table, like so:
$(document).ready(function () {
fillThatTable();
$('#thatTable').footable();
});
And instead of getting something beautiful, I just receive an average filtered table, almost like I didn't put that $('#thatTable').footable(). I checked the JS are imported, they are. Is it maybe because the table doesn't have anything in the tbody? What am I missing?
Dream:
Reality:
I've updated PM's fiddle to make an easier use of FooTable: http://jsfiddle.net/0pb4x7h6/1
If your html changes to this:
<table id="thatTable" class="table toggle-circle">
<thead>
<tr>
<th data-name="ID">ID</th>
<th data-name="FieldA">FieldA</th>
<th data-name="FieldB" data-breakpoints="all">FieldB</th>
<th data-name="FieldC" data-breakpoints="all">FieldC</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan="4">
<div class="text-right">
<ul class="pagination"></ul>
</div>
</td>
</tr>
</tfoot>
</table>
Then you can simplify your script to this:
$(document).ready(function () {
var list = [
{"ID":"1","FieldA":"A1","FieldB":"B1","FieldC":"C1"},
{"ID":"2","FieldA":"A2","FieldB":"B2","FieldC":"C2"},
{"ID":"3","FieldA":"A3","FieldB":"B3","FieldC":"C3"}
];
// No need for this
//fillThatTable();
$('#thatTable').footable({
rows: list
});
});

Can anyone help me convert a table such as this example into a dynamic one in Javascript by using the for loop?

Can anyone help me learn how to convert an HTML table into a dynamic Javascript table using the for loop? This is an example I found in my book and wanted to see how I could go about doing this.
Heading There is sections of the table that need to have the rows combined and he columns combined. I have been struggling with this for some time. Any help would be appreciated. I did not include the CSS portion of the code only the table.
<html>
<body>
<table class="table">
<tr>
<th colspan= "3" class= "MH">Conversion Tables</th>
</tr>
<tr>
<th rowspan="3" class="heading1">Meters to
<br />Feet</th>
<td>1 meter</td>
<td>3.28 feet</td>
</tr>
<tr class="difrow">
<td>50 meters</td>
<td>164.04 feet</td>
</tr>
<tr>
<td>100 meters</td>
<td>328.08 feet</td>
</tr>
<tr class="difrow">
<th rowspan="3" class="heading1">Kilometers to
<br />Miles</th>
<td>1 kilometer</td>
<td>0.62 miles</td>
</tr>
<tr>
<td>50 kilometers</td>
<td>31.07 miles</td>
</tr>
<tr class="difrow">
<td>100 kilometers</td>
<td>62.14 miles</td>
</tr>
</table>
</body>
</html>
you can add id attribute to table tag then call a javascript method on page load:
<table class="table" id="tableId">
function createRows(){
var items = "<tr><td></td></tr>...";
document.getElementById("tableId").innerHTML = items;
}
in javascript method you can use for to generate table rows.

Changing the <td> element of a table using DOM

I have been learning about DOMs lately and have been stuck on a problem for days. For some reason, I cannot change the contents of a html table. I have been looking at w3 schools HTML and using DOM to change the table element.
Here is the code for the table :
<div id="courseSummaryContainer" class="tab">
<table cellspacing="0" class="summaryTable courseSummary smallFontTable" summary="Health Care by province">
<thead><tr>
<th>Name</th>
<th>Description</th>
<th>Date of entry</th>
<th>Rating</th>
<th>Grade</th>
<th>Submission entry type</th>
</tr></thead>
<tbody>
<tr class="row-even">
<td>Illinois</td>
<td>Online system</td>
<td>201602</td>
<td>0100</td>
<td>5</td>
<td>Final</td>
</tr>
<tr class="row-odd">
<td>Alabama</td>
<td>Regional area health</td>
<td>201606</td>
<td>0100</td>
<td>7</td>
<td>Final</td>
</tr>
<tr class="row-even">
<td>Illinois</td>
<td>Online system</td>
<td>201602</td>
<td>0100</td>
<td>5</td>
<td>Final</td>
</tr>
</tbody>
</table>
</div>
What I have been trying to do is change the names of the states and their values. To do so, I have been trying to access the <td> element.
To change the contents, I tried the following:
Say for example want to change "Illinois" to "Georgia" I tried the following
document.getElementById("table.summaryTable.courseSummary.sm‌allFontTable").rows[‌2].cells;
x[1].innerHTML = "Georgia";
I am not sure what I am doing wrong however the console keeps giving errors all the time stating the values are null.
Can somebody please offer their guidance?
Use document#querySelector. In this case a simple selector can be .row-even > td:first-child because you only have one .row-even.
How can you be more specific?
If you've got multiple .row-even, by using tbody > tr:nth-child(1) > td:first-child.
If you have multiple tables with .row-even, you can add the id of the container #courseSummaryContainer .row-even > td:first-child or the class of the table .courseSummary .row-even > td:first-child.
var td = document.querySelector('.row-even > td:first-child');
td.innerText = 'Georgia';
<div id="courseSummaryContainer" class="tab">
<table cellspacing="0" class="summaryTable courseSummary smallFontTable" summary="Health Care by province">
<thead><tr>
<th>Name</th>
<th>Description</th>
<th>Date of entry</th>
<th>Rating</th>
<th>Grade</th>
<th>Submission entry type</th>
</tr></thead>
<tbody>
<tr class="row-even">
<td>Illinois</td>
<td>Online system</td>
<td>201602</td>
<td>0100</td>
<td>5</td>
<td>Final</td>
</tr>
<tr class="row-odd">
<td>Alabama</td>
<td>Regional area health</td>
<td>201606</td>
<td>0100</td>
<td>7</td>
<td>Final</td>
</tr>
</tbody>
</table>
</div>
You are not getting the right element in the DOM, if you are going to use the function: "getElementById", you need to pass it the id of the element that you want to have, like:
html:
<div id="courseSummaryContainer" class="tab">
<table id="myTable" cellspacing="0" class="summaryTable courseSummary smallFontTable" summary="Health Care by province">
//... Table content
</table>
</div>
js:
document.getElementById("myTable").rows[‌2].cells;

Data Table hangs sporadically (No data available in table) when data sorted or loaded with Knockout binding

I am binding data to a table using Knockout JS and the JQuery/Bootstrap based; Data Table API. The table becomes unresponsive sporadically when sorted or loaded. There are no errors in the log.
It also shows 0 of 0 data as illustrated in the screenshot below:
I have seen similar errors/issues but could not get a solutions for them, E.g. This post:
Code:
function viewModel(){
var self = this;
self.Data = ko.observableArray([]);
$.getJSON('https://restcountries.eu/rest/v1/all', function(data){
self.Data(data);
});
}
ko.applyBindings(viewModel());
$(document).ready(function() {
$('#example').dataTable();
});
HTML:
<div class="table-responsive">
<table id="example" cellspacing="0"
class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th scope="col">Country</th>
<th scope="col">Capital</th>
<th scope="col">Population</th>
<th scope="col">Region</th>
</tr>
</thead>
<tfoot>
<tr>
<th scope="col">Country</th>
<th scope="col">Capital</th>
<th scope="col">Population</th>
<th scope="col">Region</th>
</tr>
</tfoot>
<tbody data-bind="foreach: Data">
<tr>
<td data-bind="text: name"></td>
<td data-bind="text: capital"></td>
<td data-bind="text: population"></td>
<td data-bind="text: region"></td>
</tr>
</tbody>
</table>
</div>
Here is a full working example (JSFiddle) utilizing a REST API so that the exact problem is accurately replicated:
I think the problem with your example may be with how you're dealing with your data when you get it back from the API call.
I've put together a quick example that achieves what I think you're trying to achieve and the sorting and searching work quickly for me.
When I get the JSON data back from the API, I use the Knockout arrayMap utility function to create an array of "Country" objects that have observable properties that I have mapped the JSON data to. I've bound the table to my observableArray of Country objects.
Initialising the data table in the same way you have works fine for me in this case.
The full working solution is here: http://plnkr.co/edit/eroIox6zqBFOVnf86Mdk?p=preview
script.js
var ViewModel = function(jsonData) {
var countries = ko.utils.arrayMap(jsonData, function(item) {
return new Country(item)
});
this.Countries = ko.observableArray(countries);
};
var Country = function(jsonItem) {
this.Name = ko.observable(jsonItem.name);
this.Capital = ko.observable(jsonItem.capital);
this.Population = ko.observable(jsonItem.population);
this.Region = ko.observable(jsonItem.region);
};
window.onload = function() {
$.getJSON('https://restcountries.eu/rest/v1/all', function(data) {
ko.applyBindings(new ViewModel(data));
$("#example").dataTable();
});
}
index.html
<table id="example" cellspacing="0" class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th scope="col">Country</th>
<th scope="col">Capital</th>
<th scope="col">Population</th>
<th scope="col">Region</th>
</tr>
</thead>
<tfoot>
<tr>
<th scope="col">Country</th>
<th scope="col">Capital</th>
<th scope="col">Population</th>
<th scope="col">Region</th>
</tr>
</tfoot>
<tbody data-bind="foreach: Countries">
<tr>
<td data-bind="text: Name"></td>
<td data-bind="text: Capital"></td>
<td data-bind="text: Population"></td>
<td data-bind="text: Region"></td>
</tr>
</tbody>
</table>
Tables are fairly slow to render within Knockout, and if your table is based on a computed, I could see how you could have some issues with redrawing time. But that's not happening here.
Apart from loading the data and binding it to the table rows, there's no data manipulation going on in your viewmodel. All the data manipulation is done by the dataTable plug-in, which you initialize with a single jQuery call. Properly, that should be done within a binding handler. You also need to know what is going on within the plug-in when it sorts, filters, or whatever it does, because you may need to mediate those changes back to your observableArray within your binding handler.
Bottom line: you need a binding handler for the dataTable. There may be one already written; I haven't Googled for it. Give that a try.

Javascript <tbody> swapping not working

I've got a couple tables whose content should change based on clicking certain buttons (in this case, links). I've used this Javascript code elsewhere successfully, though with only one parameter in the switchid() function (there was only one table to mess around with). I keep researching examples of this and I seem to be passing the variables correctly, so what am I doing wrong? This code doesn't work on Chrome or IE:
Edit: Per the comments, I was able to whittle my javascript section down to a single, smaller function, that should do the same thing. I have made the change below. It still doesn't work, though.
I also changed my "array" and "x" variables to "JonArray" and "JonX" to avoid any chances of one of those being a reserved word.
<!DOCTYPE html>
<html>
<body>
<script type="text/javascript">
var topTable = new Array('English','Spanish');
var bottomTable = new Array('Japanese','Italian');
function switchid(JonArray,JonX) {
for(var i=0;i<JonArray.length();i++) {
document.getElementById(JonX).style.display='none';
}
document.getElementById(JonX).style.display='table-row-group';
}
</script>
<table border='1'>
<thead>
<tr><td>Odds</td><td>Evens</td></tr>
</thead>
<tfoot>
<tr><td>English</td><td>Spanish</td></tr>
</tfoot>
<tbody id='English'>
<tr><td>One</td><td>Two</td></tr>
<tr><td>Three</td><td>Four</td></tr>
</tbody>
<tbody id='Spanish' style="display:none;">
<tr><td>Uno</td><td>Dos</td></tr>
<tr><td>Tres</td><td>Quatro</td></tr>
</tbody>
</table>
<br />
<table border='1'>
<thead>
<tr><td>Odds</td><td>Evens</td></tr>
</thead>
<tfoot>
<tr><td>Japanese</td><td>Italian</td></tr>
</tfoot>
<tbody id='Japanese'>
<tr><td>Ichi</td><td>Ni</td></tr>
<tr><td>San</td><td>Shi</td></tr>
</tbody>
<tbody id='Italian' style="display:none;">
<tr><td>Un</td><td>Due</td></tr>
<tr><td>Tre</td><td>Quattro</td></tr>
</tbody>
</table>
</body>
</html>
http://jsfiddle.net/92ZPM/1/
I made sure the function and variables were available regardless of when they are created.
I also gave your variables descriptive names, cleaned up and stored the table data in a single object.
JavaScript
window.switchid = function (table, language) {
var tables = {
'top': ['English', 'Spanish'],
'bottom': ['Japanese', 'Italian']
};
for (var i = 0; i < tables[table].length; i++) {
document.getElementById(tables[table][i]).style.display = 'none';
}
document.getElementById(language).style.display =
'table-row-group';
}
HTML
<table border='1'>
<thead>
<tr>
<td>Odds</td>
<td>Evens</td>
</tr>
</thead>
<tfoot>
<tr>
<td>English
</td>
<td>Spanish
</td>
</tr>
</tfoot>
<tbody id='English'>
<tr>
<td>One</td>
<td>Two</td>
</tr>
<tr>
<td>Three</td>
<td>Four</td>
</tr>
</tbody>
<tbody id='Spanish' style="display:none;">
<tr>
<td>Uno</td>
<td>Dos</td>
</tr>
<tr>
<td>Tres</td>
<td>Quatro</td>
</tr>
</tbody>
</table>
<br />
<table border='1'>
<thead>
<tr>
<td>Odds</td>
<td>Evens</td>
</tr>
</thead>
<tfoot>
<tr>
<td>Japanese
</td>
<td>Italian
</td>
</tr>
</tfoot>
<tbody id='Japanese'>
<tr>
<td>Ichi</td>
<td>Ni</td>
</tr>
<tr>
<td>San</td>
<td>Shi</td>
</tr>
</tbody>
<tbody id='Italian' style="display:none;">
<tr>
<td>Un</td>
<td>Due</td>
</tr>
<tr>
<td>Tre</td>
<td>Quattro</td>
</tr>
</tbody>
</table>
you have to change your javascript a little:
var tables=new Array();
tables['topTable'] = new Array('English','Spanish');
tables['bottomTable'] = new Array('Japanese','Italian');
function switchid(JonArray,JonX) {
//alert(JonArray);
var tmptable=tables[JonArray];
for(var i=0;i < tmptable.length;i++) {
document.getElementById(tmptable[i]).style.display='none';
}
document.getElementById(JonX).style.display='';
}
Some of these answers work, but I just caught the REAL answer via Chrome DevTools! In my 'for' loop I was using 'length()' instead of 'length'!!!
Why not to use CSS instead of looping through IDs?
JSFiddle
HTML
<table border='1' class="English">
<thead>
<tr><td>Odds</td><td>Evens</td></tr>
</thead>
<tfoot>
<tr><td onclick="changeLang(this,'English')">English</td><td onclick="changeLang(this,'Spanish')">Spanish</td></tr>
</tfoot>
<tbody id='English'>
<tr><td>One</td><td>Two</td></tr>
<tr><td>Three</td><td>Four</td></tr>
</tbody>
<tbody id='Spanish'>
<tr><td>Uno</td><td>Dos</td></tr>
<tr><td>Tres</td><td>Quatro</td></tr>
</tbody>
</table>
CSS
tbody {
display: none;
}
.English #English, .Spanish #Spanish, .Japanese #Japanese, .Italian #Italian {
display: table-row-group;
}
JS
function changeLang(cell, lang) {
cell.parentNode.parentNode.parentNode.className = lang;
}

Categories