Goal: Attempting to create a feature where a table is updated with added rows from the database.
I'm running into an issue with how the views are formatted, my knowledge with javascript and MVC isn't strong enough to know which direction to go.
I have the main view, and from there I load in three partialViews separately via an ajax call which populates the div with the defined ID
<div class="container-fluid">
<div id="preTestSteps">
</div>
<div id="mainTestSteps">
</div>
<div id="postTestSteps"></div>
</div>
With the following function that loads these partial views;
$(document).ready(function() {
var testSuiteExecutionId = #(Model.TestSuiteExecutionId);
var testSuiteId = #(Model.TestSuiteId);
loadTestStepResultsPartialView(testSuiteExecutionId, testSuiteId, 1, "preTestSteps");
loadTestStepResultsPartialView(testSuiteExecutionId, testSuiteId, 0, "mainTestSteps");
loadTestStepResultsPartialView(testSuiteExecutionId, testSuiteId, 2, "postTestSteps");
});
function loadTestStepResultsPartialView( testSuiteExecutionId, testSuiteId, testStepType, divId) {
$.ajax({
type: 'POST',
url: '#Url.Action("DetailsTestStepResults", "TestSuiteExecutions")',
data: { 'testSuiteExecutionId': testSuiteExecutionId, 'testSuiteId': testSuiteId, 'testStepType': testStepType },
success: function(data) {
$("#" + divId).html(data);
}
});
}
This is working as intended.
Within these partial views, the model for the view is a list of view models, these view models are iterated over with the list of logs defined within them.
Partial View loaded from main view;
<div class="container-fluid">
#foreach (var testStep in Model)
{
<div class="row">
<div class="col-sm-12">
<h5 style="background-color: beige; padding: 5px">
#Html.DisplayFor(modelItem => testStep.TestStepName)
</h5>
</div>
</div>
<div>
#Html.Partial("~/Views/TestSuiteExecutions/TestStepLogsPartialView.cshtml", testStep.TestStepLogs)
</div>
<div>
#Html.Partial("~/Views/TestSuiteExecutions/TestStepLogsPartialView.cshtml", testStep.VerificationLogs)
<div style="padding-bottom: 25px" class="row"></div>
</div>
}
</div>
This is where things start breaking down. The partial views this partial view loads contain the logs and the table.
Log Partial View
#if (Model.Count > 0)
{
var accordianStepItemName = "accordianStep" + Model[0].TestStepId + Model[0].MessageType;
var collapseStepItemName = "collapseStep" + Model[0].TestStepId + Model[0].MessageType;
<!--TODO: Use PartialViews-->
<div class="row">
<div id="accordion" role="tablist" style="margin-left: 30px" aria-multiselectable="true">
<div id="transparent-card" class="card" style="border-color: white;">
<h6 class="mb-0">
<a data-toggle="collapse" data-parent="##accordianStepItemName" href="##collapseStepItemName" aria-expanded="false" aria-controls="#collapseStepItemName">
<i class="fa fa-plus"></i>
<i class="fa fa-minus"></i>
#(Model[0].MessageType == false ? Html.Raw("Verification Log") : Html.Raw("Execution Log"))
</a>
</h6>
<div id="#collapseStepItemName" class="collapse col-sm-12" role="tabpanel" aria-labelledby="headingOne">
<div class="card-body">
<table class="table" id="logTable_#Model[0].TestStepId#Model[0].MessageType">
<thead>
<tr>
<th width="5%"></th>
<th width="20% !important">Time</th>
<th width="75%">Message</th>
</tr>
</thead>
<tbody>
#foreach (var logEntry in Model)
{
<tr id="tableRow_#logEntry.TestStepId#logEntry.MessageType">
<td><img width="20" height="20" src="~/Content/Images/#HtmlUtilities.GetTestSuiteExecutionIconName(logEntry.LogType)" /></td>
<td><i>#logEntry.TimeStamp</i></td>
<td><i>#Html.Raw(HtmlUtilities.GetHtmlFormattedString(logEntry.Message))</i></td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
}
I'm attempting to write a javascrtipt method that will call an ajax call to bring up new log models in a list, and then add new rows to the table, but I'm running into two issues.
1) How do I pass the partial views table id's to the javascript function to execute the update? If I don't have the unique ID's (because this is looped and it needs unique Id's based on what I'm trying to update) then I can't even find the element to attach the new rows to in the script
2) How do I even attach to the table? I've attempted to use static data, but in attempting to access the table within the partial view to just prove I can actually add rows, I get 'getElementsByTagName' is null error in the debug menu.
Is what I'm attempting even possible with the current layout of the view(s)? Would it be better served to simply use one view model and put all of this logic on a single page to make the javascript easier to handle/actually function?
You can achieve this by following:
Create a partial view for row.
Segregate tables with some unique filters may be the css class.
Use those id to append rows.
Related
I apologize ahead of time if this question has been addressed...I looked and did not see one. I am building a web app using flask. After successfully logging in the user is routed to index.html via the following code:
#blueprint.route('/index')
#login_required
def index():
return render_template('home/index.html', segment='index')
My index.html includes an ajax request which builds and returns custom html such as:
<div class="card" style="max-width: 22rem;">
<!-- Card content -->
<div class="card-body pb-3">
<!-- Title -->
<h4 class="card-title font-weight-bold">TailNumber</h4>
<h6 class="card-subtitle text-muted d-flex justify-content-between">
<p>AircraftType</p>
<p>Operator</p>
</h6>
<div class="collapse-content">
<div class="collapse" id="tail_number" style="">
<table class="table table-borderless table-sm mb-0">
<tbody>
<tr>
<td class="font-weight-normal align-middle">Engine</td>
<td class="float-right font-weight-normal">
<p class="mb-1">2.5<span class="text-muted">IPS</span></p>
</td>
</tr>
</tbody>
</table>
</div>
<hr class="">
<button class="btn" type="button" data-toggle="collapse" data-target="#tail_number"
aria-expanded="false" aria-pressed="false" aria-controls="tail_number">Show
</button>
</div>
</div>
</div>
I also include a javascript function designed to change the text of my "collapse" button from "Show" to "Hide" and back again as the content is expanded and collapsed:
$(document).ready(function() {
$('[data-toggle="collapse"]').click(function() {
$(this).toggleClass("active");
if ($(this).hasClass("active")) {
$(this).text("Hide");
} else {
$(this).text("Show");
}
});
});
While the collapse feature of my html code works the text is not being updated. If I hard code the html instead of loading it via my ajax request then the button text changes as advertised. My assumption is that the javascript above is not being applied to the html returned by the ajax request but I am not sure how to verify this or, more importantly, correct it. My simplified ajax request is here:
<script>
$(function(){
function update_fleet_view(){
// create an ajax request
var req = new XMLHttpRequest();
req.open("GET", "/ajax", true);
req.send();
req.onload = function () {
// update page with new fleet view
var data = JSON.parse(req.responseText);
document.getElementById("fleet_view").innerHTML = data["fleet_view"];
// timeout to run again after 1 minute
setTimeout(update_fleet_view, 60000);
}
}
// call the function to get it started
update_fleet_view();
})();
</script>
Event delegation was exactly what I needed...thanks for the link James.
I ended up with the following modifications to my JS:
$(document).ready(function() {
$("#fleet_view").on("click", '[data-toggle="collapse"]', function() {
if ($(this).hasClass("collapsed")) {
$(this).text("Hide");
} else {
$(this).text("Show");
}
});
});
where "fleet_view" is the "id" that is referenced by my ajax script.
I attempted to leave the $(this).toggleClass("active") in the script however I could never get it to toggle. Rather than spending precious time tracking that issue down I decided to look at the "collapsed" field as the click event toggles that automatically. I also had to modify my button to add the "collapsed" class otherwise the button text would not update for the first round of clicks (see code below). The "if/else" statement seems backwards but I assure you it works as intended. Again, I can only assume that the "collapsed" class gets added or removed after this script executes.
<button class="btn collapsed" type="button" data-toggle="collapse" data-target="#tail_number"
aria-expanded="false" aria-pressed="false" aria-controls="tail_number">Show
</button>
I'm developing a MeteorJS app and I'm dynamically adding a data-target attribute for activating a modal and three of the additions are acting normal and producing correct results, yet the first target repeatedly calls the method which eats up CPU and RAM, and breaks what I'm trying to accomplish. The one fix I found is to add null/hidden tag that calls the method first but this doesn't fix the issue repeated calls that eat up CPU and RAM.
HTML:
{{#each getCategories}}
<div class="row hidden-sm hidden-md hidden-lg visible-xs-block">
<div class="col-xs-10">
<h2>{{this.category}}</h2>
</div>
<div class="col-xs-2">
<!--
Must have this null element for some odd reason
the first call to getUniqueID continuous runs and breaks
this functionality so this a quick fix
-->
<!-- <null style="display:none;">{{getUniqueID}}{{getUniqueID}}</null> -->
<span data-toggle="modal" data-target="#submit_{{getUniqueID}}"><i class="fa fa-plus-circle fa-3x" aria-hidden="true"></i></span>
{{>cardSumbitModal category=this.category id=getUniqueID}}
</div>
</div>
{{#each cards this.category}}
<div class="row hidden-sm hidden-md hidden-lg visible-xs-block">
<div class="col-xs-12">
{{>card id=_id color=../color}}
</div>
</div>
{{/each}}
{{/each}}
JS:
getUniqueID: function(){
var id = Session.get("roomNumber");
var count = Session.get("getUniqueID_CallCount");
id = id + count;
if(!Session.get("pairSet")){
Session.set("pairSet", true);
}else{
count++;
Session.set("pairSet", false);
}
Session.set("getUniqueID_CallCount",count);
return id;
}
Because helpers are designed to be reactive they can run much more often than you expect. You should setup the getCategories helper to map an array and include the unique id as a an extra column so it doesn't need to be computed with every document/row.
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 have a table inside a bootstrap modal. The content that I populate inside the dataTable cells is quite large, and instead of wrapping the text to fit the table inside the modal, it overflows the modal, like it is unable to pick up the modal width and wrap the text.
Screenshot:
I have tried various solutions, such as specifying wrap CSS as well as specifying the table width (in % and px) and setting the width property on the table (in % and px) but there is absolutely no change to the table. Any advice on how to correct this issue would be greatly appreciated.
Code Extract 1 (Modal):
<!-- List Questions Modal -->
<div class="modal fade" id="questionsModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog" style="width: 95%">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4>Questions</h4>
</div>
<div class="modal-body">
<div class="row">
<div class="responsive-table">
<table width="900px" class="table table-bordered" style="margin-bottom:2em; width: 900px;" id="questionsTable">
<thead>
<tr>
<th >Code</th>
<th>Title</th>
<th>Instruction</th>
<th>Extract</th>
<th>class="text-center">Active</th>
<th class="text-center">Edit</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
</div>
Code Extract 2 (dataTable population):
function showQuestions(quiz_id)
{
$('#questions_quiz_id').val('quiz_id');
window.questionsTable.fnClearTable();
$.post('{{ url("getGameQuestions") }}', {quiz_id : quiz_id})
.done(function(data)
{
if (typeof(data.error) != 'undefined')
{
$('#error-msg').html(data.error);
$('#page-error').fadeIn(300).delay(2000).fadeOut(500);
}
else
{
for(var d in data)
{
var question = data[d];
var active = (question.active == undefined || question.active == false) ? "Inactive" : "Active";
var ai = window.questionsTable.fnAddData([
question.code,
question.title,
question.instruction,
question.extract,
active,
'<i class="icon-pencil" style="cursor:pointer; color:#E48A07;" title="Edit" onclick="setQuestion('+question.id+')"></i>'
]);
var oSettings = window.questionsTable.fnSettings();
var addedRow = oSettings.aoData[ai[0]].nTr;
addedRow.cells.item(2).setAttribute('width','29%');
addedRow.cells.item(4).className = "text-center";
addedRow.cells.item(4).className = "text-center";
addedRow.cells.item(5).className = "text-center";
}
$('#questionsModal').modal('show');
}
});
}
Try removing
<div class="responsive-table"> it might be causing responsive widths in the modal to fail.
You could also try specifying a max-width on the table.
This might be slightly related although it was a problem with Bootstrap 2.3.2 and it looks like you are using 3.
http://www.bootply.com/88364
This question is asked here
datatables does not becomes responsive on bootstrap3 modal dialog
I would suggest you enable the Datatables Responsive extension, ditch the wrapper and use this snippet of code instead.
//once the modal has been shown
$('#yourModal').on('shown.bs.modal', function() {
//Get the datatable which has previously been initialized
var dataTable= $('#yourResponsiveDataTableInModal').DataTable();
//recalculate the dimensions
dataTable.columns.adjust().responsive.recalc();
});
After trying so many solutions i found one who works for me!
Just put the table inside a div and define the CSS inside the code.
<div style="overflow:auto;">
<table>
.....
</table>
</div>
I hope this help!!
Remove the <div class="row"> and check.
Am also experienced same problem,after i removed the div, i got it perfectly.
After trying so many solutions i found a solution.
Just put the table inside a div and define the CSS inside the code.
<div style="overflow:auto;">
<table>
.....
</table>
</div>
I hope this help!!
<div class="modal-body">
<div class="row table-responsive">
<div class="col-sm-12">
<table id="example" class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th class="site_name">
Feedback
</th>
<th>
Ticket Id
</th>
<th>
Date of Creation
</th>
<th>
Classification
</th>
<th>
Topic
</th>
<th></th>
</tr>
</thead>
</table>
</div>
</div>
</div>
initialize the datatable like that
initialize the datatable when open the modal.first time when we open the modal i==1 second thime i==2 so datatble cant reinitalize again and again does not give any alert box like datatable already initalize
var i=1;
$('#myModal').on('shown.bs.modal', function (e) {
if(i==1){
var oTable=$('#questionsTable').DataTable();
}
i++;
});
Just insert your table inside a div with "table-responsive" class:
<div class="table-responsive">
//Your table here
</div>
I am trying to make an angular.js view update itself when adding a comment. My code is as follows:
<div class="comment clearfix" data-ng-repeat="comment in currentItem.comments" data-ng-class="{bubble: $first}" data-ng-instant>
<div>
<p>
<span class="username">{{comment.user}}</span> {{comment.message}}
</p>
<p class="time">
10 minutes ago
</p>
</div>
</div>
<div class="comment reply">
<div class="row-fluid">
<div class="span1">
<img src="assets/img/samples/user2.jpg" alt="user2" />
</div>
<div class="span11">
<textarea class="input-block-level addComment" type="text" placeholder="Reply…"></textarea>
</div>
</div>
</div>
the scope is updated on enter:
$('.addComment').keypress(function(e) {
if(e.which == 10 || e.which == 13) {
$scope.currentItem.comments.push({
"user": "user3",
"message": $(this).val()
});
console.debug("currentItem", $scope.currentItem);
}
});
debugging $scope.currentItem shows that the comment has been added to it, however the view doesn't show the new comment. I suspect that the $scope is only being watched on its first level and that this is why the view doesn't update. is that the case? If so how can I fix it?
SOLUTION:
As Ajay suggested in his answer below I wrapped the array push into the apply function like this:
var el=$(this);
$scope.$apply(function () {
$scope.currentChallenge.comments.push({
"user": $scope.currentUser,
"message": el.val()
});
});
Modify the code to wrap inside scope.$apply because you are modifying the property outside the angular scope you have to use scope.$apply() to watch the values
I had to place my form inside the same div controller as the ng-repeat. I had two separate div controllers.
Use $scope.$parent.arrayObjet to modify the parent variables instead of $scope.arryaObject. It worked in my case.
<div class="col-sm-12 col-lg-12">
<div class="outer-container">
<div class="inner-container">
<div class="table-header">
<form id="teamForm" name="teamForm">
<table class="table table-bordered">
<thead>
<!-- Grid header -->
<tbody data-ng-if="(allTeamMembers.length==0)">
<tr>
<td class="text-center height_33_p" colspan="15"> {{noResultFound}} </td>
</tr>
</tbody>
<!-- Existing team member -->
<tbody data-ng-repeat="tm in teammemberDetailsArryobject|orderBy:orderByField:reverseSort" data-ng-form="innerForm_$index" data-ng-class="{'ng-submitted':innerForm_$index.$submitted}">
<tr></tr>
</tbody>
In the code I am deleting one record and add new row programmatically but all the rows are displayed in the ng-repeat rows(including deleted)