So, the _form.gsp template associated with my create.gsp creates an initial table from a template for the row as follows:
<table id="myTable">
<!-- define table headers here -->
<g:each var="i" in="${1..5}">
<g:render template="tableRow" model="['i': i]" />
</g:each>
</table>
What I'd like to do is add a button or a link underneath that table that let's you add five more rows, while keeping all the data you've entered in the form so far.
I can see how that's possible in "pure" javascript, but I'd basically have to repeat the _myTable.gsp HTML in my javascript file. I'd like to avoid that (DRY, etc.).
How can I do that?
Edit
So, I tried Gregg's solution (below). Here's what I came up with.
The Controller has an action:
def addMoreRows() {
println params
def i = params.rowNumber + 1
def j = i+5
println "i is set to " + i
render(template: "foapRow", bean:i, var:i, model: ['rowStart': i, 'rowEnd': j])
}
The create.gsp page calls the _form.gsp as normal, adding a rowStart and a rowEnd to the model.
create.gsp
<g:render template="form" model="['userId':userId, 'rowStart':1, 'rowEnd':5]"/>
*_form.gsp*, in turn, passes those parameters on to the row template, and creates a link to call the above controller action. It also has the javascript Gregg recommended:
<script type="text/javascript">
$("#addRowsLink").on("click", function(e) {
e.preventDefault();
$.get("/Controller/addMoreRows", function(html) {
$("#theTableInQuestion>tbody").append(html);
});
});
</script>
<table>
...
<g:render template="tableRow" model="['rowStart':1, 'rowEnd':5]"/>
</table>
<g:remoteLink id="addRowsLink" action="addMoreRows" update="theTableInQuestion" onSuccess="addRows(#theTableInQuestion, data, textStatus)" params="['rowNumber':data]">Add More Rows</g:remoteLink>
The *_tableRow.gsp* begins and ends with:
<g:each var="i" in="${rowStart..rowEnd}">
<tr>
...
</tr>
</g:each>
From a previous attempt, I have this function in my included javascript file:
function addRows(tableId, rowCode, status) {
$(tableId + ' tr:last').after(rowCode);
}
Right now, when I click the "Add More Rows" link, I still get taken to a new page, and it only has one row on it.
One possible solution. You're going to need to change your template so it does the looping:
GSP:
<table id="myTable">
<tbody>
<g:render template="tableRows" model="[loopCount:loopCount, moreData:moreData]" />
</tbody>
</table>
Template:
<g:each in="${loopCount}" var="idx">
<tr>
<td>.....</td>
......
</tr>
</g:each>
JavaScript:
$("#someButtonId").on("click", function(e) {
e.preventDefault();
$.get("/controller/someAction", function(html) {
$("#myTable>tbody").append(html);
});
});
Controller:
def someAction = {
// logic here
render template: "tableRows", model="[loopCount: 5, moreData:moreData]"
}
You could also submit all the data in your table to the server every time and refresh the entire page, adding logic to loop over some variable number of rows. But you would need to collect all that data on the server and make sure it gets put back in the request.
There's probably a dozen ways to do this so don't be surprised if you get that many answers. :o)
Related
I'm trying to display a table on a new page by calling an API and loading the data in the table. This page is loaded on click of a menuItem.
But the issue I'm facing is that the table is displaying, but not the data I'm intending to. I know that I'm able to fetch the data from the API since i can see that in the console log.
Here is the code:
In this first html file im clickling the menu and calling my next html page i want to load
and also im giving my id="covidLink" which im calling in my JS FILE.
pan.html
<div class="navbar">
<a class="covidText" id="covidLink" href="covidStatusUpdate.html">Covid-19</a>
</div>
In the below js file im making a call to the api and appending the data in tbody.
Fetchdata.js
$(document).ready(function () {
$("#covidLink").click(function () {
console.log("Link clicked...");
requestVirusData();
});
});
function requestVirusData() {
$.getJSON('https://api.covid19api.com/summary',
function(data){
var countries_list = data.Countries;
//console.log(countries_list);
$(countries_list).each(function(i, country_dtls){
$('#totalbody').append($("<tr>")
.append($("<td>").append(country_dtls.country))
.append($("<td>").append(country_dtls.TotalConfirmed))
.append($("<td>").append(country_dtls.TotalDeaths))
.append($("<td>").append(country_dtls.TotalRecovered)));
});
})
}
and lastly
statusUpdate.html
<table class="table table-striped table-bordered table-sm" cellspacing="0" width=80%>
<thead>
<tr>
<th>Country</th>
<th>TotalConfirmed</th>
<th>TotalDeaths</th>
<th>TotalRecovered</th>
</tr>
</thead>
<tbody id="totalbody">
</tbody>
</table>
What am I supposed to do ? I have to admit that I'm lost here.
I don't think you quite understand how AJAX works. You're handling a click on "covidLink". This does two things simultaneously.
it tells the browser to navigate away from the current page and go to statusUpdate.html instead.
it runs the requestVirusData() function. This gets the data from the API and returns it to the page.
But the problem is: the API call returns the data to the page where the script was called from - i.e. it returns it to pan.html. And you've just told the browser to move away from that page. Also, pan.html doesn't contain a table to put the returned data into.
The logical solution here is to link to fetchdata.js from statusUpdate.html instead, and tweak the code slightly so it runs when that page loads, rather than on the click of a button:
$(document).ready(function () {
console.log("page loaded...");
requestVirusData();
});
As suggested by ADyson i did changes in my code and now im able to display the table with data.
Here are my code changes:
statusUpdate.html
<tbody id="tbody">
<script>
var datatable;
fetch('https://api.covid19api.com/summary')
.then(function (response) {
return response.json();
})
.then(function (data) {
appendData(data);
})
.catch(function (err) {
console.log('error: ' + err);
});
function appendData(data) {
var countries_list = data.Countries;
var tbody = document.getElementById("tbody");
// clear the table for updating
$('table tbody').empty();
// hide the table for hidden initialize
$('table').hide();
// loop over every country
for (var i in countries_list) {
var country_dtls = countries_list[i];
// replace -1 with unknown
for (var o in country_dtls) {
if (country_dtls[o] == -1) country_dtls[o] = 'Unknown';
}
$('table tbody').append(`
<tr>
<td>${country_dtls.Country}</td>
<td>${country_dtls.TotalConfirmed}</td>
<td>${country_dtls.TotalDeaths}</td>
<td>${country_dtls.TotalRecovered}</td>
</tr>`);
}
}
// }
</script>
</tbody>
pan.html
<a class="covid" href="statusUpdate.html">Covid-19</a>
and now i do not need fetchdata.js obviously.
Hope this helps someone stuck like me :)
My purpose:
I want to show treeview data in table. I use Angularjs and treeview to realize this feature. However, when the JS script get the data and give the data to treeview, the data will show for just a second and disappear.
html code like this:
<tbody id="understanding-content-table-body">
<tr ng-repeat="(i, log) in understandingLogs">
<td ng-repeat="item in log track by $index">{{item}}</td>
<td>
<div id="tree-{{i}}"></div>
</td>
</tr>
</tbody>
And my JS code like this:
for (var i = 0; i < tmp.length; ++i) {
var id = '#tree-' + i;
$(id).treeview({ data: tmp[i], levels: 0, showBorder: false, icon: "glyphicon glyphicon-minus" });
}
tmp is the data that want to show.
After debugging, I found that when the the JS script finished, another angularjs code will be executed, and then the treeview in the table will disappear. I think
that the treeview doesn't find the "tree-0", "tree-1"... because the html don't ready. And I execute the command
$('#tree-0').treeview({ data: [{text:123}], levels: 0, showBorder: false, icon: "glyphicon glyphicon-minus" });
then the data will be shown in the table.
So my question is that, could I execute the JS script after the html is finished?
By the way, I have tried the
angular.element(document).ready(function () {});
and
$('document').ready(function (){});
It doesn't work.
Following is the static html of the table. i dyanamically insert table based on the no of data i get(data.length) value that i get from the ajax call.
Now i need to insert pagination in this where only 5 tables been allowed and if it exceeds to 6th, dyanamically pagination should happen where the values in the footer should increase by one( << < 1 2 > >> ).
<table id="myTable">
<tbody id="tBody">
<td>
<tr>sample values</tr>
<tr>sample values</tr>
<td>
</tbody>
</table>
for(int i=0;i>data.length;i++)
{
var Row = $("#myTable #tBody").append("<td><tr></tr></td>");
}
I made use of the following script but the problem here is, pagination didnt happen. not sure of where the problem exists since am just a beginner to JS.
<script src=../../simplepagination.js>
// init bootpag
$('#page-selection').bootpag({
total: 10
}).on("page", function(event, num){
$("#content").html("Insert content");
});
</script>
This is my first MVC application, and this must be something simple but I've been trying to make this work for so many hours now..
What I want to do
I want to display a table in a partial view and be able to delete items from the parent view. The simple version looks something like this (the actual application is not about fruits):
What I have now
Partial View (_FruitList.cshtml)
<div id="listOfFruits">
<table class="table">
<tr>
<th class="active">Description</th>
<th class="active">Amount</th>
</tr>
#foreach(var item in Model)
{
<tr>
<td>#item.Description</td>
<td>#item.Amount</td>
<td><button class=".." onclick="d(#item.FruitID)">Delete</button></td>
</tr>
}
</table>
</div>
Parent View (Home.cshtml)
#section scripts
{
<script type="text/javascript">
$(document).ready(function (){
function d(id){
var url = "/Fruit/DeleteFruit/";
$.post(url, {id: id})
.done(function(response){
$("#listOfFruits").html(response);
});
}
});
</script>
}
#{Html.RenderPartial("_FruitList", Model.FruitList);}
Controller (FruitController.cs)
[HttpPost]
public ActionResult DeleteFruit(int id)
{
//Delete the selected fruit
FruitViewMode item = new FruitViewMode();
return PartialView(item.FruitList);
}
My Question
I can view the table with the fruit data in the parent view, but clicking the Delete button does not call the d function in the parent view.
(Javascript and JQuery should be working in the partial view because I've tested alert and addClass and they work fine)
I'm very new to this so it's very likely that I'm missing some basic stuff but what am I missing?
d() isn't declared in the global page scope, so it isn't found. declare it in the root of the <script> tag (i.e., not within a document.ready) to have access to it from the onclick
<script type="text/javascript">
function d(id){
var url = "/Fruit/DeleteFruit/";
$.post(url, {id: id})
.done(function(response){
$("#listOfFruits").html(response);
});
}
</script>
I believe in the past I had used a HTML.ActionLink for the same goal of deleting something by Id:
HTML.ActionLink method
I'm having two tables witch renders data trough angularJs, coming from 2 c#-methods.
The tables are structured almost exactly the same. The first one below is used as I searchfield and the other one is used basiclly to render names.
My problem is that the first one works perfect, but the other one does not. And I don't see the problem. Any help would be appreciated. // Thanks!
Here are my two tables. (the first one is working)
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.18/angular.min.js"></script>
<div ng-app="searchApp">
<div ng-controller="searchController">
#*first table works*#
<span style="color: white">Search:</span> <input data-ng-click="myFunction()" ng-model="searchText">
<table style="color: white" id="searchTextResults">
<tr><th>Name</th></tr>
<tr ng-show="!!searchText.length != 0" ng-repeat="friend in friends | filter:searchText">
<td data-id="{{friend.id}}" data-ng-click="SendFriendRequest(friend.id)">{{friend.id.replace("RavenUsers/","")}}</td>
</tr>
</table>
#*Does not work*#
<input type="button" value="Get friends requests" data-ng-click="GetFriendRequests()">
<table style="color: white">
<tr><th>Friend requests</th></tr>
<tr ng-repeat="friendRequest in friendRequests">
<td data-id="{{friendRequest.UserWhoWantsToAddYou}}" data-ng-click="acceptUserRequest(friendRequest.UserWhoWantsToAddYou)">{{friendRequest.UserWhoWantsToAddYou}}</td>
</tr>
</table>
</div>
</div>
HERE IS MY SCRIPT
<script>
var App = angular.module('searchApp', []);
App.controller('searchController', function ($scope, $http) {
//Get all users to the seachFunction
$scope.myFunction = function () {
var result = $http.get("/Home/GetAllUsersExeptCurrentUser");
result.success(function (data) {
$scope.friends = data;
});
};
//Get friendRequests from other users
$scope.GetFriendRequests = function () {
var result = $http.get("/Home/GetFriendRequests");
result.success(function (data) {
$scope.friendRequests = data;
});
};
});
</script>
The first script-function called myFunction works perfect and the data coming from my c#-method looks like this:
[{"id":"RavenUsers/One"},{"id":"RavenUsers/Two"},{"id":"RavenUsers/Three"}]
The second script-function called GetFriendRequests does not work, and as far as I can see there is no difference between this data passed into here than the data passed into myFunction:
[{"userWhoWantsToAddYou":"RavenUsers/Ten"},{"userWhoWantsToAddYou":"RavenUsers/Eleven"}]
I'd suggest you use then instead of success because $http returns a promise.
If your table doesn't "render" then put a breakpoint inside success function, console.log() the data or check friendRequests inside your HTML template, e.g. using <div>{{ friendRequests | json }}</div>, to ensure you actually got data from response.
Now you do not handle exceptions at all.
Example:
result.then(function(data) {
console.log('got data')
},function(error) {
console.log('oh noes :( !');
});
Related plunker here http://plnkr.co/edit/KzY8A3
It would be helpful if you either (a) provided a plunker to your code or (b) provided the error message.
ng-repeat requires a uniquificator on each item in the repeat, which defaults to item.id. If you don't have an id field on the item, you'll need to tell angular what field to use.
https://docs.angularjs.org/api/ng/directive/ngRepeat
So I'd suggest changing
<tr ng-repeat="friendRequest in friendRequests">
to
<tr ng-repeat="friendRequest in friendRequests track by userWhoWantsToAddYou">
and see if that works.