I'm using angular 13 and bootstrap 3 and making an app which contains two components: form-component ( to input details about a user ) and list-component ( to display all the data in a table ). Inside my main app component html, I have a table template that calls my list component for values inside the table body:
<table class="table table-bordered">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Email</th>
<th>Contact</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<app-contact-list
*ngFor="let itemElement of listData; let ind=index"
[item]="itemElement"
[i]="ind">
<button class="btn btn-primary" type="button">View</button>
<button class="btn btn-primary" type="button">Update</button>
<button class="btn btn-primary" type="reset" (click)="removeItem(itemElement)">Delete</button>
</app-contact-list>
</tbody>
</table>
inside my list component I wanted to loop these data to the table:
<tr>
<td><span>{{i}}</span></td>
<td><span>{{item.name}}</span></td>
<td><span>{{item.email}}</span></td>
<td><span>{{item.contact}}</span></td>
<td>
<ng-content></ng-content>
</td>
</tr>
But running the app displays all the data in one cell that looks like this:
https://i.stack.imgur.com/Mziwx.jpg
and adding another one gives me:
https://i.stack.imgur.com/Zu6M2.jpg
The table rows have detached from the table DOM element, causing them to render in one cell.
Instead of including the header and rows within the same component HTML, refactor them into respective components app-contact-header and app-contact-list.
The resulting HTML for <table> should include the above components wrapped within the <thead> and <tbody> elements as shown:
<table class="table table-bordered">
<thead>
<tr app-contact-header></tr>
</thead>
<tbody>
<tr
app-contact-list
*ngFor="let itemElement of listData; let ind = index"
[item]="itemElement"
[i]="ind"
></tr>
</tbody>
</table>
The components will need to be declared with an attribute selector (not to be confused with attribute directives), in order to be injected into the HTML element <tr>.
app-contact-header
HTML
<th>Id</th>
<th>Name</th>
<th>Email</th>
<th>Contact</th>
<th>Action</th>
TS
import { Component, OnInit } from '#angular/core';
#Component({
selector: '[app-contact-header]',
templateUrl: './contact-header.component.html',
styleUrls: ['./contact-header.component.css'],
})
export class ContactHeaderComponent implements OnInit {
constructor() {}
ngOnInit() {}
}
app-contact-list
HTML
<td class="col1">
<span>{{ i + 1 }}</span>
</td>
<td class="col2">
<span>{{ item.name }}</span>
</td>
<td class="col3">
<span>{{ item.email }}</span>
</td>
<td class="col4">
<span>{{ item.contact }}</span>
</td>
<td class="col5">
<button class="btn btn-primary" type="button">View</button>
<button class="btn btn-primary" type="button">Update</button>
<button class="btn btn-primary" type="reset" (click)="removeItem(item)">
Delete
</button>
</td>
TS
import { Component, Input, OnInit } from '#angular/core';
#Component({
selector: '[app-contact-list]',
templateUrl: './contact-list.component.html',
styleUrls: ['./contact-list.component.css'],
})
export class ContactListComponent implements OnInit {
#Input() item: any;
#Input() i: number;
constructor() {}
ngOnInit() {}
...
}
}
Using HTML <table> elements is not responsive. In future consider using <div> and <span> elements to render columns and rows.
Related
This is my controller class read data method. I cant read spring data from requesting. when I do it from postman it works fine but cant read using html page.
#RequestMapping("/index")
public String ItemList(Model model) {
model.addAttribute("itemList", repository.findAll());
return "index";
}
Like this I try to read data using my index.html page
<h2>Medicine List</h2>
<form action="/index" method="POST">
<table>
<thead>
<tr>
<th>ID</th>
<th>MedicineName</th>
<th>Description</th>
<th>Quantity</th>
<th>Price</th>
<th>ExDate</th>
</tr>
</thead>
<tbody>
<tr th:each="item:${itemList}">
<td th:text="${item.id}"></td>
<td th:text="${item.MedicineName}"></td>
<td th:text="${item.Description}"></td>
<td th:text="${item.Quantity}"></td>
<td th:text="${item.Price}"></td>
<td th:text="${item.ExDate}"></td>
<td><form action="/delete/item:${itemList}" method="Delete"><input type="submit" value="Delete" /></form></td>
</tr>
</tbody>
</table>
</form>
<table class="table">
<tr>
<th>Name</th>
</tr>
<tr th:each="recipe : ${recipes}">
<td th:text="${recipe.Name}"></td>
<td>
<span th:each="recipe,iterStat : ${recipes}">
</span>
</td>
<td>
<a th:href="#{/recipe/food/{id}(id=${recipe.id})}">view</a>
</td>
</tr>
I am trying to click this link above, utilizing this controller
#RequestMapping(value="recipe/food/{id}", method = RequestMethod.POST)
public String viewRecipe(#PathVariable int id, Model model){
model.addAttribute("name", recipeDao.findOne(id));
model.addAttribute("recipeText", recipeDao.findOne(id));
return "Recipes/food" ;
}
to display a single item, based on its id here
<table class="table">
<tr>
<th>Name</th>
</tr>
<form method ="post" th:action="recipe/food/{id}" th:object=${recipe}">
<tr th:each="recipe : ${recipes}">
<td th:text="${recipe.name}">text</td>
<td th:text="${recipe.recipeText}">text</td>
</tr>
<span th:errors="*{recipeText}" class="error"></span>
</form>
however i only get a 404, but the url information is correct
When you click the link it will execute a GET-request, so try changing the method in the Controller to method = RequestMethod.GET or simply remove method = RequestMethod.POST.
Update:
The part of the food template that is in the third code snippet is looping over a list named recipes, but the Controller method isn't adding a list as an attribute to the model only "name" and "recipeText". What you want is probably the template to display the recipe that you clicked the link for? Something like <h4 th:text="${name}"></h4> <span th:text="${recipeText}" />
I have tried to send a parameter from this thymleaf page
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Email</th>
<th>Send Invoice</th>
</tr>
</thead>
<tbody>
<tr class="table-row" th:each="p : ${POList}">
<td th:text="${p.email}"></td>
<td>
<form style='float:left; padding:5px; height:0px' th:object="${p}" th:method="post" th:action="#{/dashboard/makeAndSendInvoice/{email}(email=${p.email})}">
<button class="btn btn-default btn-xs" type="submit">Send Invoice</button>
</form>
</td>
</tr>
</tbody>
and then I tried to receive the parameter (email) using this code
#RequestMapping(method=POST, path="/makeAndSendInvoice/{email}")
public void makeAndSendInvoice(#PathVariable("email") String email) throws Exception {
System.out.println("Invoice is sent to..................."+email);
}
The problem is when the value of p.email is something like myemail#gmail.com
what I receive in the method makeAndSendInvoice is only myemail#gmail
and it does not send me the .com part
How can I fix it?
(email=${p.email}) means , you are passing a query parameter.
So, how can you be able to catch the query param value using path variable?
We can use #RequestParam to catch the queryparam value in Spring
Try the below java code :
#RequestMapping(method=POST, path="/makeAndSendInvoice/{email}")
public void makeAndSendInvoice(#RequestParam("email") String email) throws Exception {
System.out.println("Invoice is sent to..................."+email);
}
The period in ".com" will need to be encoded to be used in the url to prevent it being parsed as the suffix
Your HTML:
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Email</th>
<th>Send Invoice</th>
</tr>
</thead>
<tbody>
<tr class="table-row" th:each="p : ${POList}">
<td th:text="${p.email}"></td>
<td>
<form method="post" th:action="#{/dashboard/makeAndSendInvoice/__${p.email}__} ">
<button class="btn btn-default btn-xs" type="submit">Send Invoice</button>
</form>
</td>
</tr>
</tbody>
Your controller
#RequestMapping(value = "/dashboard")
#Controller
public class testController {
...
#RequestMapping(value = "/makeAndSendInvoice/{email}", method = RequestMethod.POST)
public ModelAndView makeAndSendInvoice(#PathVariable String email, ModelAndView mav) {
return mav; // <- Break point, debug !!
}
}
I have a problem where in i have to fetch the particular data of row on clicking that particular rows button and have to display that data via ajax on the same page.
Here is the code of index.scala.html:
#(products: List[Products])
#import helper._
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<h1>#products.size() product(s)</h1>
<table border=1>
<tr>
<td>Product Name</td>
<td>Quantity</td>
<td>Price</td>
</tr>
#for(product <- products) {
<tr>
<td>
#product.productname
</td>
<td>
#product.quantity
</td>
<td>
#product.price
</td>
<td>
<input type="button" value="Add Product" name="#routes.Application.user(#product.product_id)" id="but"/>
</td>
</tr>
}
</table>
<div class="result" style="border: 1px solid black; padding: 5px;">not sent yet...</div>
<script type="text/javascript">
jQuery("#but").click(
function () {
$.get(jQuery(this).attr("name"), function (data) {
$('.result').html(data);
});
return false;
}
)
</script>
My Application.java contains the method as shown below:
public static Result user( id){
return ok("Play's controller told that you're about to get data for user no. "+id);
}
The problem i am facing is in the line:
**<input type="button" value="Add Product" name="#routes.Application.user(#product.product_id)" id="but"/>**
Error is: Compilation error
illegal start of simple expression
Can anyone please help to load the dymanic data.
Please remove the second #:
#routes.Application.user(product.product_id)
The second one is not needed, since the first indicates that you're in the templating language.
Question is i have table in which i want to populate the values of file name and file size after user click the choose file button and select any number of files, Now the issue is if the user click choose files button second time i want to append the new values in the table and add the new file in the array so that it can uploaded.. my code is,
html form code:
<form id="simpleuploadform" method="post" action="upload" enctype="multipart/form-data">
<table class="span10" border="0">
<tr>
<td colspan="3">
<legend>Simple Upload</legend>
</td>
</tr>
<tr>
<td>
<input type="file" name="files[]" multiple="multiple" onchange="getFileSizeandName(this);"/>
<div id="successdiv" hidden="true" class="label label-success">Image uploaded successfully</div>
<div id="errordiv" hidden="true" class="label label-error">Image not successfully uploaded</div>
<div id="streamdiv" hidden="true" class="label label-warning">Issue while uploading try again</div>
</td>
<td id="renameFile" align="right"></td>
<td id="removeFile" align="right"></td>
</tr>
<tr>
<td colspan="3">
<div id="uploaddiv">
<table id="uploadTable" class="table table-striped table-bordered" width="200" height="200" scrolling="yes">
<thead>
<tr>
<th>Title</th>
<th>Size</th>
</tr>
</thead>
<tbody id="tbodyid">
<tr id="tr0">
<td id="filetd0" height="10px" width="50px"></td>
<td id="filesizetd0" height="10px" width="5px"></td>
</tr>
<tr id="tr1">
<td id="filetd1" height="10px" width="50px"></td>
<td id="filesizetd1" height="10px" width="5px"></td>
</tr>
<tr id="tr2">
<td id="filetd2" height="10px" width="50px"></td>
<td id="filesizetd2" height="10px" width="5px"></td>
</tr>
<tr id="tr3">
<td id="filetd3" height="10px" width="50px"></td>
<td id="filesizetd3" height="10px" width="5px"></td>
</tr>
<tr id="tr4">
<td id="filetd4" height="10px" width="50px"></td>
<td id="filesizetd4" height="10px" width="5px"></td>
</tr>
</tbody>
<tfoot>
<tr>
<td id="filecount" height="10px" width="50px"></td>
<td id="totalsize" height="10px" width="5px"></td>
</tr>
</tfoot>
</table>
</div>
</td>
</tr>
<tr>
<td colspan="3">
<input type="submit" class="btn btn-primary" onClick="CloseAndRefresh();" value="Start Upload" id="startButton" disabled>
<input type="reset" class="btn btn-primary" onClick="Clear();" value="Clear" id="clearButton" disabled>
<input type="button" class="btn" onClick="window.close();" value="Close">
</td>
</tr>
</table>
javascript code:
<script type="text/javascript">
var totalsizeOfUploadFiles = 0;
function getFileSizeandName(input)
{
var select = $('#uploadTable tbody');
$('#renameFile').empty();$('#removeFile').empty();
if(input.files.length > 0)
{
$('#renameFile').append($('<a id="renameRec">Rename Selected</a>'));
$('#removeFile').append($('<a id="removeRec">Remove Selected</a>'));
$('#startButton').removeAttr("disabled", "disabled");
$('#clearButton').removeAttr("disabled", "disabled");
}
//if(input.files.length <= 5)
//{
for(var i =0; i<input.files.length; i++)
{
var filesizeInBytes = input.files[i].size;
var filesizeInMB = (filesizeInBytes / (1024*1024)).toFixed(2);
var filename = input.files[i].name;
//alert("File name is : "+filename+" || size : "+filesizeInMB+" MB || size : "+filesizeInBytes+" Bytes");
if(i<=4)
{
$('#filetd'+i+'').text(filename);
$('#filesizetd'+i+'').text(filesizeInMB);
}
else if(i>4)
select.append($('<tr id=tr'+i+'><td id=filetd'+i+'>'+filename+'</td><td id=filesizetd'+i+'>'+filesizeInMB+'</td></tr>'));
totalsizeOfUploadFiles += parseFloat(filesizeInMB);
$('#totalsize').text(totalsizeOfUploadFiles.toFixed(2)+" MB");
if(i==0)
$('#filecount').text("1file");
else
{
var no = parseInt(i) + 1;
$('#filecount').text(no+"files");
}
}
//}
}
function CloseAndRefresh()
{
var daa = '<%=status%>';
if(daa == "true")
$('#successdiv').show();
else if(daa == "false")
$('#errordiv').show();
else
$('#streamdiv').show();
opener.location.reload(true);
self.close();
}
function Clear()
{
$('#uploadTable tbody tr td').each(function(){
$(this).text("");
});
$('#uploadTable tfoot tr td').each(function(){
$(this).text("");
});
}
i am trying to do as like this http://www.shutterfly.com/ image upload.
any help will be appreciated, thank you friends...
You are navigating away using javascript, function CloseAndRefresh on clicking submit button.
What actually happens is that the uploading request is being submitted while the CloseAndRefresh function is being executed at almost the same time using different thread. If the upload request is not fast enough, the web page will get refresh first and your upload request get terminated immediately. There is no easy way to prevent this using your existing code.
You should use advanced method of uploading like jQuery uploading plugin to send the request. The plugin provide an binder to execute function on successful/failed submittsion.
Thank you gigadot, i solve the issue as like below,
The html form have the same code as i posted earlier, in the previous js code i have the CloseAndRefresh() method i remove it now from js as well as from the submit button onclick event.
When the form action called the controller, in which i have the code
#RequestMapping(value = "/upload", method = RequestMethod.POST)
public String UploadReceipts(#RequestParam("files[]") List<MultipartFile> file, Model model) throws IOException {
boolean status = false;
try
{
for(int i=0; i< file.size(); i++)
{
if(!file.get(i).isEmpty())
{
CommonsMultipartFile cm = (CommonsMultipartFile) file.get(i);
status = simpleUploadService.uploadFileandSave(cm);
model.addAttribute("status", status);
}
}
}
catch (IOException e) {
status = false;
model.addAttribute("status", status);
}
return "pages/simpleUploadStatus";
}
Now i redirect it to another page in which i throws the appropriate messages for the user.
that's all...