Angular JS displaying a specific ng-grid in a ng-repeat - javascript

Friends, i have a tree that is dynamically created from JSON. It also creates the grids that i want for a particular element on the tree and hides them all. Then i have a ng-click that shows it. My problem is that it shows ALL of them instead of the one that i want. For example, if user clicks on the header in 'Record 1' it should display the first grid and so on and so on. Here is my JSBin.
My HTML looks like this. Please see my JSBin for JavaScript file:
<body ng-controller="AbnTestController" style="margin:20px">
<button ng-click="try_changing_the_tree_data()" class="btn btn-default btn-sm">Submit File</button>
<p>
<table width="100%" style="height: 100%;" cellpadding="10" cellspacing="0" border="0">
<tr>
<!-- ============ LEFT COLUMN (TREE) ============== -->
<td width="250px" style="vertical-align:top" bgcolor="whitesmoke">
<div style="width:250px;background:whitesmoke;border:1px solid lightgray;border-radius:5px;">
<abn-tree ng-click="visible.grid = true" tree-data="my_data" tree-control="my_tree" on-select="my_tree_handler(branch)" expand-level="2"></abn-tree>
</div>
</td>
<!-- ============ RIGHT COLUMN (CONTENT) ============== -->
<td width="80%" valign="top" bgcolor="#d2d8c7">
<div style="vertical-align:top;">
<div ng-repeat="rule in rules">
<div ng-show="visible.grid == true" class="gridStyle" ng-grid="rule.grid" ></div>
</div>
<div id="results"></div>
</div>
</td>
</tr>
</table>
</p>
</body>

Here's a jsbin
HTML (diff):
<div ng-repeat="rule in rules">
<div
ng-show="rulesMap[rule.uid] == 'isVisible'"
class="gridStyle"
ng-grid="rule.grid"></div>
</div>
JavaScript remove calls to createGrids and:
$scope.my_tree_handler = function(branch) {
createGridsFromBranch(branch);
};
/*Function that builds the grid*/
$scope.rulesMap = {};
$scope.rules = [];
createGridsFromBranch = function(branch) {
var gridUid = 'g_'+branch.uid;
for(var i in $scope.rulesMap) {
$scope.rulesMap[i] = 'notVisible';
}
if($scope.rulesMap[gridUid]) {
$scope.rulesMap[gridUid] = 'isVisible';
return;
}
$scope.rulesMap[gridUid] = 'isVisible';
$scope.rules.push({
uid: gridUid,
grid: {
...
}
});

Related

Ternary operator in Template Literal HTML TABLE

I am trying to set my table data to have a background color of red if it has a "Failed" status. I am having a hard time setting this inline style. At first I tried to use the ternary operator in the second td of the createTableData function but could not get it to work. Right now I am attempting to break it out into its own function but not working either.
Looking for help on setting the background color of my table data.
HTML
<body>
<div class="container-fluid">
<div class="jumbotron">
<h1 class="text-center mb-3">
Active Directory Replication Health
</h1>
</div>
<div id="table"></div>
</div>
<script src="js/jquery-3.3.1.min.js"></script>
<script src="js/bootstrap.bundle.min.js"></script>
<script src="js/script.js"></script>
Script
var data = [
{
"DC": "SV07CTDC1",
"Connectivity": "Passed",
"Advertising": "Failed"
},
{
"DC": "SVGCCTDC1",
"Connectivity": "Passed",
"Advertising": "Failed"
}
];
function checkStatus(status) {
status === "Failed" ? "background-color: red" : "background-color: blue"
}
function createTableData(dc ){
var html = ''
for( key in dc )
html += `
<tr>
<td> ${key} </td>
<td style=${checkStatus(dc[key])} > ${dc[key]} </td>
</tr>
`
return html
}
function createTable(dc) {
return `
<div class="col-md-3 col-sm-6 ">
<table class="table table-dark table-striped table-bordered table-hover">
${createTableData(dc)}
</table>
</div>
`
}
document.getElementById("table").innerHTML = `
<div class="row">
${data.map(createTable).join("")}
</div>
`
The only thing you're missing in your checkStatus method is to return the condition result;
function checkStatus(status) {
return status === "Failed" ? "background-color: red" : "background-color: blue"
}
updated codepen

Problems displaying dataTable in modal in html partial view

I asked a question here yesterday about this issue but got downvoted, probably because I didn't include any code which is understandable.
Hopefully this question will be more complete and allow you to help me more easily.
So I have 3 views in play:
StudentsList
Script
#{
ViewBag.Title = "StudentsList";
Layout = "~/Views/Shared/_LayoutM.cshtml";
}
#Scripts.Render("~/Scripts/charts")
#Styles.Render("~/Content/formsaltcss")
#model Mvc.Models.StudentViewModel
<script type="text/javascript">
$(document).ready(function () {
$('#AddStudentData').click(function () {
var type = 'student';
var id = 0;
$('#holderArea').html('');
if (!$('#studentDropDown option:selected').length) {
ToastrWarning('Please select a student before running the report');
return;
}
id = $('#studentDropDown').val();
var data = { id: id };
$.ajax({
url: '/Student/StudentAnalysisFiltered',
async: false,
data: data,
dataType: 'html',
success: function (data) {
$('#holderArea').html(data);
}
});
});
});
Relevant HTML
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="margin-bottom0 text-center">Student Analysis</h3></div>
<div class="panel-body">
<div class="row">
<div class="col-sm-12">
<form class="form-horizontal">
<div class="form-group">
<div class="row">
<label class="col-sm-2 control-label">Student Name</label>
<div class="col-sm-4">
#Html.DropDownListFor(c => c.Students, new SelectList(Model.Students, "StudentID", "Name"), "Choose Student"
, new { id = "studentDropDown", #class = "form-control input-sm", data_width = "100%" })
</div>
<div class="col-sm-offset-2 col-sm-10">
<button id="AddStudentData" type="button" class="btn btn-sm btn-primary">Select</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<div id="holderArea">
</div>
StudentAnalysisSelected
Script
#using Data
#using Mvc.Helpers
#model Mvc.Models.StudentViewModel
#Scripts.Render("~/Scripts/datatables")
<script>
function StudentScoresModal(studentID, answer, result) {
$('#scoresTable').hide();
$('#scoresSpinner').show();
$('#scoresModal').modal('show');
var testID = #Html.Raw(Model.testID );
$.ajax({
cache: false,
url: "/Student/StudentScoresDrillthrough",
data: { 'studentID': studentID, 'answer': answer, 'result': result, 'testID': testID},
success: function (data) {
$('#scoresTable').html(data);
$('#scoresTable').show();
$('#scoresSpinner').hide();
},
error: function () {
toastr.options.positionClass = 'toast-bottom-right';
toastr.options.backgroundpositionClass = 'toast-bottom-right';
toastr.options.timeOut = 3000;
toastr.error('Unable to get student results.');
}
});
}
</script>
Relevant HTML
<div id="holderArea">
<button type="button" class="btn btn-sm btn-primary" onclick="StudentScoresModal(id, '', '')" id="#q.StudentID">View Scores</button>
</div>
<div class="modal in modal-stack" id="scoresModal" aria-hidden="false">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title"><strong>Student Scores</strong></h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-xs-12">
<div class="table-responsive" id="scoresTable" style="display:none">
</div>
<div class="sk-cube-grid absolute-center top-85" id="scoresSpinner" style="display:none">
<div class="sk-cube sk-cube1"></div>
<div class="sk-cube sk-cube2"></div>
<div class="sk-cube sk-cube3"></div>
<div class="sk-cube sk-cube4"></div>
<div class="sk-cube sk-cube5"></div>
<div class="sk-cube sk-cube6"></div>
<div class="sk-cube sk-cube7"></div>
<div class="sk-cube sk-cube8"></div>
<div class="sk-cube sk-cube9"></div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-sm btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
StudentScoresPartial
Script
<script>
$(document).ready(function () {
$('#studentScores').dataTable({
"data": #Html.Raw(Model.StudentScoresJson),
"columns":[
{ "sName": "StudentID" },
{ "sName": "Answer" },
{ "sName": "Result" }
]
});
});
</script>
HTML
<table id="studentScores" class="display table table-bordered" cellspacing="0" width="100%">
<thead>
<tr>
<th>StudentID</th>
<th>Answer</th>
<th>Result</th>
</tr>
</thead>
<tfoot>
<tr>
<th>User</th>
<th>Answer</th>
<th>Response</th>
</tr>
</tfoot>
<tbody></tbody>
</table>
How it all works
On the 'StudentsList' view there is a dropdown with list of students, and a 'Select' button to filter on an individual. OnClick this clears the holderArea div and passes studentID to the controller method, which returns a partial view 'StudentAnalysisSelected' and places it inside the holderArea div.
Now a graph is loaded with details specific to the indivudual. When clicked the 'scoresTable' is hidden and the modal is shown and an ajax call is made to StudentScoresDrillthrough controller, which returns the 'StudentScores' partial that is placed into the html of 'scoresTable'.
The problem
Now this all works perfectly first time I filter by student. I click 'Select', the graph loads, I click the graph and the datatable displays neatly in the modal.
However for reasons unknown to me when I click 'Select' again to re-filter, and click on the graph that is loaded all I see is the modal appear with the loading spinner, and it stops there. No errors pertaining to datatables in the console, or anything out of the ordinary for that matter.
I appreciate this is a bit of a read, but i'd be keen to hear any thoughts on what could be causing my issue.
Thanks!
It's because your dom is reloaded and so you loose your event attached.
If you attach ypur event like so, this should do, see doc :
$('#AddStudentData').on('click',function () {});
First try calling dataTable after filter button click using $('#studentScores').dataTable();
If this doesn't work
Instead on your refilter click write:
$('#studentScores').dataTable();
After your partialview is fully loaded. And bind your list in table directly e.g :
StudentID
Answer
Result
#foreeach(var item in Model)
{
item.User
item.Answer
item.Response
}
Finally tracked it down and it was because the modal show was called before the table show.
Thanks to those who posted suggestions, it's much appreciated

Hide complex column with colspan and rowspan with jQuery

I am building more or less a complex table with a lot of colspan and rowspan td's. Now i would like to create an onclick event on those pink column. So as soon as you click on one of these + column with class collapse, i would like to hide columns. For example, when I click the first +, I would like to hide the whole First driver column including Driver Name, first-driver-01, Driver ID, etc.
nth-child(x) is not helping really, because it does not ignore the col- and rowspans. I tried to group the td's in a seperated tag, like this:
<tr>
<td rowspan="3">CIM</td>
<!-- First driver -->
<group class="first-driver-01">
<td colspan="4">First driver</td>
</group>
<td rowspan="3" class="collapse">+</td>
<group class="second-driver-213">
<td colspan="4">Second driver</td>
</group>
<td rowspan="3" class="collapse">+</td>
</tr>
Unfortunately my chrome browser does this to the tags:
I'd use div's and CSS for something like this and style them like a table. I'm not going to re-create your entire table but here is an example I made using a smaller table, I'll leave you to have some fun.
Javascript
document.getElementById("clickme").onclick = function(){
var divsToHide = document.getElementsByClassName("hide"); //divsToHide is an array
if(document.getElementById("clickme").innerHTML == "-"){
for(var i = 0; i < divsToHide.length; i++){
divsToHide[i].style.visibility = "hidden"; // or
divsToHide[i].style.display = "none"; // depending on what you're doing
}
document.getElementById("clickme").innerHTML = "+"
}
else {
for(var i = 0; i < divsToHide.length; i++){
divsToHide[i].style.visibility = "visible"; // or
divsToHide[i].style.display = "table-cell"; // depending on what you're doing
}
document.getElementById("clickme").innerHTML = "-"
}
};
HTML
<div class="table">
<div class="row">
<div class="cell header">Team</div>
<div class="cell header">Wins</div>
<div class="cell header">Losses</div>
<div class="cell header hide ">Pct</div>
</div>
<div class="row">
<div class="cell">Bulls</div>
<div class="cell">29</div>
<div class="cell">18</div>
<div class="cell hide">.617</div>
</div>
<div class="row">
<div class="cell">Pacers</div>
<div class="cell">28</div>
<div class="cell">19</div>
<div class="cell hide">.596</div>
</div>
<div class="row">
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell" id="clickme">-</div>
</div>
CSS
.table {
display:table;
}
.row {
display:table-row;
}
.cell {
display:table-cell;
padding:2px;
}
.header {
font-weight:bold;
text-align:center;
}
Fiddle Here
I hope this helps,
Good luck

Display image as none on drop event

So I have 2 columns filled with images. I want to drag an image from the left column and drop it on the right column's image. The original image on the left must then have it's display set to none so that it disappears.
Here is an example of the html:
<div id="container1">
<table class="table1">
<tr>
<td>
<div class="info1" id="info1" ondragover="allowDrop(event)" ondrop="drop(event)">
<div style="float:left">
<img class="myimg" style="max-height:80px;" src="Pictures/Smiley.png">
</div>
<div style="float:left;">
<p class="myname">Name: Jane Doe</p>
<p class="myprof">Profession: Carpenter</p>
</div>
</div>
</td>
</tr>
</table>
</div>
<div id="container2">
<table class="table2">
<tr>
<td>
<div class="info2" onmousedown = "returnDrop(this.querySelector('img').src)" ondragover="allowDrop(event)" ondrop="drop()" >
<div style="float:left">
<img class="myimg2" style="max-height:80px;" src="Pictures/QuestionMark.png">
</div>
<div style="float:left;">
<p class="myname2">Name: Unspecified</p>
<p class="myprof2">Profession: Unspecified</p>
</div>
</div>
</td>
</tr>
</table>
</div
Here is some of the Javascript I've tried - it's probably best not to look as it as it simply doesn't work. I can use jquery if it's necessary.
document.getElementsByClassName('info2')[0].drop = function() {
document.getElementsByClassName('myimg2')[0].src = storeOnClick;
document.getElementsByClassName('myname2')[0].innerHTML=name;
document.getElementsByClassName('myprof2')[0].innerHTML=prof;
updateRecord();
return;
}
function updateRecord(div){
div.parentNode.parentNode.parentNode.style.display='none';
}
function returnDrop(el){
if(el=="file:///C:/Users/nmonk/Desktop/Tree/Pictures/QuestionMark.png"){
}
else if(el=="file:///C:/Users/nmonk/Desktop/Tree/Pictures/Smiley.png"){
updateRecord1(el);
}
else if(el=="file:///C:/Users/nmonk/Desktop/Tree/Pictures/Smiley2.png"){
updateRecord2(el);
}
else if(el=="file:///C:/Users/nmonk/Desktop/Tree/Pictures/Smiley3.png"){
updateRecord3(el);
}
else if(el=="file:///C:/Users/nmonk/Desktop/Tree/Pictures/Smiley4.png"){
updateRecord4(el);
}
else if(el=="file:///C:/Users/nmonk/Desktop/Tree/Pictures/Smiley5.png"){
updateRecord5(el);
}
}
function allowDrop(ev) {
ev.preventDefault();
}
Necessary but unrelated to the issue:
function start(){
first();
}
function first () {
var _divs = document.querySelectorAll('.info1');
for (var i = 0; i < _divs.length; i++) {
_divs[i].addEventListener("mousedown", function () { changeInfo1(this) }, false);
}
}
function changeInfo1(el) {
myimg = el.querySelector('.myimg'),
myname = el.querySelector('.myname'),
myprof = el.querySelector('.myprof')
// img
storeOnClick = myimg.src;
// name
name = myname.innerHTML;
// profession
prof = myprof.innerHTML;
}
You could very simply add the following for each of your images: (note the last line)
document.getElementsByClassName('info2')[0].drop = function() {
document.getElementsByClassName('myimg2')[0].src = storeOnClick;
document.getElementsByClassName('myname2')[0].innerHTML=name;
document.getElementsByClassName('myprof2')[0].innerHTML=prof;
if(storeOnClick=='file:///C:/Users/nmonk/Desktop/Tree/Pictures/Smiley.png'){
document.getElementsByClassName('info1')[0].parentNode.style.display='none';
}

creating a toggle button to change page views

I am using knockout js to get my data to display and i am also using it to bind templates. I have a page that displays the same information in two different ways: one is a grid view and the other is a list view. Currently i have both views displayed on the page load. I would like to create two buttons one for the grid and one for the list. I am not sure how to go about it with Knockout js any tips or help is appreciated.
View Page
<div data-bind="template: {name:'grid-template'}, visible: !showList()"></div>
<div data-bind="template: {name:'list-template'}, visible: showList()"></div>
<input type="button" value="Toggle" data-bind="click: toggleView"/>
<script style="float:left" type="text/html" id ="grid-template">
<section " style="width:100%; float:left">
<section id="users" data-bind="foreach: Users">
<div id="nameImage">
<figure id="content">
<img width="158" height="158" alt="Gravatar" data-bind="attr:{src: GravatarUrl}"/>
<figcaption>
<a title="Email" id="emailIcon" class="icon-envelope icon-white" data-bind="attr:{'href':'mailto:' + Email()}"></a>
<a title="Profile" id="profileIcon" class="icon-user icon-white"></a>
</figcaption>
</figure>
<p data-bind="text:Name"></p>
</div>
</section>
</section>
</script>
<script style="float:left" type="text/html" id="list-template">
<div data-bind="foreach: Users">
<div style="width:60%; float:left; margin:10px; height:58px">
<img style="float:left; margin-right:5px" width="58" height="58" alt="Gravatar" data-bind="attr:{src: GravatarUrl}"/>
<p style="height:58px; float:left; vertical-align:central" data-bind="text:Name"></p>
<a style="float:right" title="Profile" class="icon-user icon-black"></a>
<a style="float:right" title="Email" class="icon-envelope icon-black" data-bind="attr:{'href':'mailto:' + Email()}"></a>
</div>
</div>
</script>
#section scripts{
#Scripts.Render("~/bundles/user" + ViewBag.Layout.AppVersionForUrls)
<script type="text/javascript">
(function ($) {
$.views.User.GetUser('#url');
})(jQuery);
</script>
}
Knockout JS
$.views.User.UserViewModel = function (data) {
var self = this;
self.Name = ko.observable(data.Name);
self.Email = ko.observable(data.Email);
self.ContentRole = ko.observable(data.ContentRole);
self.MD5Email = ko.observable(data.MD5Email);
self.GravatarUrl = ko.computed(function () {
return 'http://www.gravatar.com/avatar/' + self.MD5Email() + '?s=300&d=identicon&r=G';
});
self.showList = ko.observable(true);
self.toggleView = function () {
self.showList(!self.showList());
}
};
If I understand correctly, you could bind the visible property of each div to a boolean that you flip each time a button is pressed.
HTML:
<input type="button" value="Toggle" data-bind="click: toggleView"/>
<div data-bind="visible: showGrid()">Grid</div>
<div data-bind="visible: !showGrid()">List</div>
View Model:
var ViewModel = function() {
var self = this;
self.showGrid = ko.observable(true);
self.toggleView = function() {
self.showGrid(!self.showGrid());
}
}
var vm = new ViewModel();
ko.applyBindings(vm);
Here's a jsFiddle.

Categories