Vue shows same ride - html

I've a table with rides like this:
<tr>
<td>{{ ride.user.name }}</td>
<td>{{ ride.location.from }}</td>
<td>{{ ride.location.to }}</td>
<td>{{ ride.type.name }}</td>
<td>{{ ride.date }}</td>
<td>
<a #click="show" class="btn-show">Show</a>
<a v-link="{ name: 'ritten' }" class="btn-edit">Bewerk</a>
<a v-link="{ name: 'ritten' }" class="btn-delete">Verwijder</a>
</td>
<td><show-ride-modal :ride="ride"></show-ride-modal></td>
</tr>
So the last td makes sure there will pop-up a modal if you click on show. In that modal more details of the selected ride are visible.
The problem is that every always the same ride is being passed to the modal. Why is that?
EDIT
<table class="table" v-if="rides">
<thead>
<tr>
<th>Door</th>
<th>Van</th>
<th>Naar</th>
<th>Type</th>
<th>Datum</th>
</tr>
</thead>
<tbody v-for="ride in rides" is="ride" :ride="ride"></tbody>
</table>

Edit: After posting this I learned that Vue.js requires special behavior in the case of tables. See: http://vuejs.org/guide/components.html#Template-Parsing.
It is hard to answer the question if we have to guess what the rest of your code looks like. However, I see some strange things in your code, so maybe if you look at those the issue can be fixed.
Look at this:
<tbody v-for="ride in rides" is="ride" :ride="ride"></tbody>
The 'is="ride"' attribute and ':ride="ride"' parts don't seem to do anything. 'is=' is used in the dynamic component element to assign the component type, and ':ride' could be used to pass props to a component. But you don't appear to have component.
My suggestion would be change the code to this:
<table class="table" v-if="rides">
<thead>
<tr>
<th>Door</th>
<th>Van</th>
<th>Naar</th>
<th>Type</th>
<th>Datum</th>
<th>Acties</th>
</tr>
</thead>
<tbody v-for="ride in rides" >
<tr>
<td>{{ ride.user.name }}</td>
<td>{{ ride.location.from }}</td>
<td>{{ ride.location.to }}</td>
<td>{{ ride.type.name }}</td>
<td>{{ ride.date }}</td>
<td>
<a #click="show" class="btn-show">Show</a>
<show-ride-modal :ride="ride"></show-ride-modal>
<a v-link="{ name: 'ritten' }" class="btn-edit">Bewerk</a>
<a v-link="{ name: 'ritten' }" class="btn-delete">Verwijder</a>
</td>
</tr>
</tbody>
</table>

Related

Export HTML DataTable to Excel - Display URL to Image in Excel

I'm trying to display an HTML DataTables URL to the actual image in an Excel column.
Right now, when I export the DataTable to Excel it populates the corresponding column with the URL itself, what I want to achieve is to actually populate the Excel column with the Image, not the Image URL.
Right now, I can see the image for the comment.screenshot variable into HTML, but in Excel, it is blank, while for the rest of comment.screenshot1,comment.screenshot2 and comment.screenshot3, only the URL is populated in Excel.
jQuery:
$("#tableComments").DataTable({
stripHtml: !1,
dom: "Bfrtip",
buttons: ["copyHtml5", "excelHtml5", "csvHtml5", "pdfHtml5"]
})
HTML:
<table id="tableComments" class="display table table-info table-striped">
<thead>
<tr>
<th>User</th>
<th>Version</th>
<th>Round</th>
<th>Comment</th>
<th>Screenshot #1</th>
<th>Screenshot #2</th>
<th>Screenshot #3</th>
<th>Screenshot #4</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{% for comment in comments %}
<tr>
<td>{{ comment.user.username }}</td>
<td>{{ comment.versionName }}</td>
<td>{{ comment.round }}</td>
<td>{{ comment.comment }}</td>
<td><img src="{{ comment.screenshot }}" /></td>
<td>{{ comment.screenshot1 }}</td>
<td>{{ comment.screenshot2 }}</td>
<td>{{ comment.screenshot3 }}</td>
<td>{{ comment.approved }}</td>
</tr>
{% endfor %}
</tbody>
</table>
I highly appreciate your help!
Instead of Datatables export buttons you may use a different approach using encodeURIComponent:
The snippet:
$("#tableComments").DataTable({
stripHtml: !1,
dom: 'Bfrtip',
buttons: ['copyHtml5', 'csvHtml5', 'pdfHtml5']
})
$('button').on('click', function(e) {
window.open('data:application/vnd.ms-excel,' + encodeURIComponent( document.getElementById('tableComments').outerHTML));
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.23/css/jquery.dataTables.min.css">
<script src="https://cdn.datatables.net/1.10.23/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/buttons/1.6.5/js/dataTables.buttons.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/pdfmake.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/vfs_fonts.js"></script>
<script src="https://cdn.datatables.net/buttons/1.6.5/js/buttons.html5.min.js"></script>
<button>Export To Excel</button>
<table id="tableComments" class="display table table-info table-striped">
<thead>
<tr>
<th>User</th>
<th>Version</th>
<th>Round</th>
<th>Comment</th>
<th>Screenshot #1</th>
<th>Screenshot #2</th>
<th>Screenshot #3</th>
<th>Screenshot #4</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>username1</td>
<td>versionName</td>
<td>round</td>
<td>comment </td>
<td><img src="https://dummyimage.com/100x100/000/fff&text=1"/></td>
<td>screenshot1</td>
<td>screenshot2</td>
<td>screenshot3</td>
<td>approved</td>
</tr>
<tr>
<td>username2</td>
<td>versionName</td>
<td>round</td>
<td>comment </td>
<td><img src="https://dummyimage.com/100x100/000/fff&text=2"/></td>
<td>screenshot1</td>
<td>screenshot2</td>
<td>screenshot3</td>
<td>approved</td>
</tr>
<tr>
<td>username3</td>
<td>versionName</td>
<td>round</td>
<td>comment </td>
<td><img src="https://dummyimage.com/100x100/000/fff&text=3"/></td>
<td>screenshot1</td>
<td>screenshot2</td>
<td>screenshot3</td>
<td>approved</td>
</tr>
</tbody>
</table>

Angular: Cannot display the content from HTTP Response using *ngFor

I tried to load the content from HTTP response to html view in the angular. I have initialized a array call 'list' to get the data. But its not visible while debugging. I don't know the issue. I'm just a beginner in angular.
<table class="table table-hover">
<th>
</th>
<tr *ngFor="let item of api.list">
<td (click)="populateForm(item)">{{ item.FirstName }}</td>
<td (click)="populateForm(item)">{{ item.LastName }}</td>
<td (click)="populateForm(item)">{{ item.Country }}</td>
<td (click)="populateForm(item)">{{ item.Phone }}</td>
<td (click)="populateForm(item)">{{ item.FavoriteFood }}</td>
<td (click)="populateForm(item)">{{ item.Comment }}</td>
<td>
<i class="far fa-trash-alt fa-lg text-danger" (click)="onDelete(item.TestRegisterId)"></i>
</td>
</tr>
</table>
i'm also attaching the behind code also. I have included the service in ngOninit().
ngOnInit() {
this.api.refreshList();
}
The refreshList function is here.
refreshList(){
this.http.get(this.rootURL)
.toPromise()
.then(res => this.list = res as RegisterModel[]);
}
my html page looks like this,
My database has 4 records, so i can see the 4 delete button. But data is not showing, i don't know why. Anyone please help me ?
Just change "this.list" to "this.api.list" (make sure you already defined "list" array in your "api"):
refreshList(){
this.http.get(this.rootURL)
.toPromise()
.then(res => this.api.list = res as RegisterModel[]);
}
the problem is that due to asynchrony you are trying to render the list when it has not yet come from the server.
you can try not rendering the list while the variable is undefined with *ngIf = this.list
Instead of looping on api.list, you need to loop our list, the one you have initialised.
<table class="table table-hover">
<th>
</th>
<tr *ngFor="let item of list">
<td (click)="populateForm(item)">{{ item.FirstName }}</td>
<td (click)="populateForm(item)">{{ item.LastName }}</td>
<td (click)="populateForm(item)">{{ item.Country }}</td>
<td (click)="populateForm(item)">{{ item.Phone }}</td>
<td (click)="populateForm(item)">{{ item.FavoriteFood }}</td>
<td (click)="populateForm(item)">{{ item.Comment }}</td>
<td>
<i class="far fa-trash-alt fa-lg text-danger" (click)="onDelete(item.TestRegisterId)"></i>
</td>
</tr>
</table>
Or if you want to loop over api.list, you need to set data to this.api.list not to this.list as below
refreshList(){
this.http.get(this.rootURL)
.toPromise()
.then(res => this.api.list = res as RegisterModel[]);
}

How to write a *ngIf statement in a table in Angular?

<table border = 2 border-bottom = 2>
<th> </th>
<th>S. No.</th>
<th>Title</th>
<th>Creation date</th>
<th>Modification date</th>
<tr *ngFor = "let checkboxesBlog of getCheckboxes_FormGroup.controls; let i = index;" >
<a *ngIf = "checkboxesBlog.controls.visible.value === true">
<td [formGroup] = "checkboxesBlog">
<input type = "checkbox"
formControlName = "checkboxValue"
(click) = "onCheckboxClicked( i )">
</td>
<td>{{ i + 1 }}</td>
<td>{{ checkboxesBlog.controls.blogTitle.value }}</td>
<td>{{ checkboxesBlog.controls.creationDate.value }}</td>
<td>{{ checkboxesBlog.controls.modificationDate.value }}</td>
</a>
</tr>
</table>
Following if clause is creating two problems above:
<a *ngIf = "checkboxesBlog.controls.visible.value === true">
The S.R. No. is not sequential because the i is getting updated in for loop.
The first column is unnecessarily too long.
What is the way to write if statements to avoid these problems?
Some HTML elements require all immediate children to be of a specific type. For example, the <tr> element requires <td> children. You can't wrap the rows in a conditional <a>.
ng-container to the rescue
The Angular <ng-container> is a grouping element that doesn't interfere with styles or layout because Angular doesn't put it in the DOM.
Here's the conditional row again, this time using <ng-container>.
<table border = 2 border-bottom = 2>
<th> </th>
<th>S. No.</th>
<th>Title</th>
<th>Creation date</th>
<th>Modification date</th>
<tr *ngFor = "let checkboxesBlog of getCheckboxes_FormGroup.controls; let i = index;" >
<ng-container *ngIf = "checkboxesBlog.controls.visible.value === true">
<td [formGroup] = "checkboxesBlog">
<input type = "checkbox"
formControlName = "checkboxValue"
(click) = "onCheckboxClicked( i )">
</td>
<td>{{ i + 1 }}</td>
<td>{{ checkboxesBlog.controls.blogTitle.value }}</td>
<td>{{ checkboxesBlog.controls.creationDate.value }}</td>
<td>{{ checkboxesBlog.controls.modificationDate.value }}</td>
</ng-container>
</tr>
</table>
For more information: https://angular.io/guide/structural-directives#ng-container-to-the-rescue
Here you go :-
<table border = 2 border-bottom = 2>
<tr>
<th> </th>
<th>S. No.</th>
<th>Title</th>
<th>Creation date</th>
<th>Modification date</th>
</tr>
<tr *ngFor = "let checkboxesBlog of filteredCheckBoxes; let i = index;" >
<a>
<td [formGroup] = "checkboxesBlog">
<input type = "checkbox"
formControlName = "checkboxValue"
(click) = "onCheckboxClicked( i )">
</td>
<td>{{ i + 1 }}</td>
<td>{{ checkboxesBlog.controls.blogTitle.value }}</td>
<td>{{ checkboxesBlog.controls.creationDate.value }}</td>
<td>{{ checkboxesBlog.controls.modificationDate.value }}</td>
</a>
</tr>
</table>
In Typescript :-
public filteredCheckBoxes = [];
ngOnInit() {
this.filterData();
}
public filterData() {
this.filteredCheckBoxes = this.getCheckboxes_FormGroup.controls.filter((data) => data.controls.visible.value);
}
This answer: https://stackoverflow.com/a/62014605/462608, throws the following error:
Property 'controls' does not exist on type 'AbstractControl'.
from the following function:
public filterData() {
this.filteredCheckBoxes = this.getCheckboxes_FormGroup.controls.filter((data) => data.controls.visible.value);
}
Way to solve that error is to use data.get('visible').value instead of data.controls.visible.value as follows:
this.filteredCheckBoxes = this.getCheckboxes_FormGroup.controls.filter( (data) => data.get('visible').value) );

Is there a way I can incorporate mailto links with ngFor?

I create an Object and use ngFor to loop through it and create a table. I would like to somehow incorporate mailto links if possible.
I have this finalResults object that looks something like this:
[
{key: 'example#example.com', value: 'message'}
]
Where message is something like
"Please contact the Login Team for help."
I would like to make Login Team a mailto link.
I have already tried making the message like this
Please contact the Login Team for help.
But on the webpage it just displayed that exactly. There was no link.
I use ngFor to loop through my object and make a table.
< <tr>
<th *ngFor="let col of displayedColumns">
{{ col }}
</th>
</tr>
<tr *ngFor="let item of finalResults">
<td>{{ item.key }}</td>
<td>{{ item.value }}</td>
</tr>
<tr></tr>
</table>
Is there some way to do this?
If you want to keep your text as html text then consider using innerHTML binding:
ts
finalResults = [
{
key: 'example#example.com',
value: 'Please contact the Login Team for help.'
}
];
html
<td [innerHTML]="item.value"></td>
Ng-run Example
In component declare
email: string = 'mailto:misesasd#gmail.com'
in template:
<a [href]="email">misesasd#gmail.com</a>
array:
<tr *ngFor="let item of finalResults">
<td><a [href]="item.key">{{item.key}}</a></td>
<td>{{ item.value }}</td>
</tr>
or:
<tr *ngFor="let item of finalResults">
<td>{{item.key}}</td>
<td>{{ item.value }}</td>
</tr>
<tr *ngFor="let item of finalResults">
<td>{{ item.value }}</td>
</tr>

ng-repeat shows only if DB return more than one result

I'm working on coupons project, and i want to display to the client all the coupons that available to purchase.
When i click on the button that call to the function "getAllCoupons()" it works and it returns the results in JSON, but when i want to Insert the results into the table with ng-repeat it displays only if the function returns more than one coupon, if there is only one coupon the ng-repeat don't displays nothing.
This is my controller
angular.module('companyApp', []);
angular.module('companyApp').controller('companyController',
function($rootScope, $scope, $http) {
$scope.getAllCoupons = function() {
$http.get("rest/CompanyService/getAllCoupon").success(
function(response) {
$scope.allCoupons = response.coupon;
});
This is my HTML
<div ng-app="companyApp" ng-controller="companyController">
<button class="tablinks" ng-click="getAllCoupons()" id="getAll">Get all coupons</button>
<table align="center" class="table table-striped" style="width: 900px;">
<thead>
<tr>
<th> Id </th>
<th>Coupon Title</th>
<th>Amount</th>
<th>Start Date</th>
<th>End Date</th>
<th>Price</th>
<th>Message</th>
<th>Coupon Type</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="x in allCoupons">
<td>{{ x.id }}</td>
<td>{{ x.title }}</td>
<td>{{ x.amount }}</td>
<td>{{ x.startDate }}</td>
<td>{{ x.endDate }}</td>
<td>{{ x.price }}</td>
<td>{{ x.message }}</td>
<td>{{ x.type }}</td>
</tr>
</tbody>
</table>
</div>
But if i write it without the ng-repeat it works and i get it in JSON:
<div ng-app="companyApp" ng-controller="companyController">
<button class="tablinks" ng-click="getAllCoupons()" id="getAll">Get all coupons</button>
{{ allCoupons }}
</div>
The response for single coupon is:
{"coupon":{"amount":"149","endDate":"04/12/2020","id":"6","message":"only big sizes","price":"79.9","startDate":"07/08/2014","title":"pajamas","type":"FASHION"}}
And the response for multiple coupons is:
{"coupon":[{"amount":"60","endDate":"05/09/2020","id":"5","message":"warranty for 1 year","price":"200.99","startDate":"20/02/2014","title":"sunglasses","type":"FASHION"},{"amount":"149","endDate":"04/12/2020","id":"6","message":"only big sizes","price":"79.9","startDate":"07/08/2014","title":"pajamas","type":"FASHION"}]}
Thanks for help :)
You are referencing an object not an array, check the docs for using an object in ngRepeat's arguments.
You would need ng-repeat="(key, value) in allCoupons
Try this
<tr ng-repeat="(key, value) in allCoupons">
<td>{{ value.id }}</td>
<td>{{ value.title }}</td>
<td>{{ value.amount }}</td>
<td>{{ value.startDate }}</td>
<td>{{ value.endDate }}</td>
<td>{{ value.price }}</td>
<td>{{ value.message }}</td>
<td>{{ value.type }}</td>
</tr>
Hope it helps
The server's response for a single coupon is in a different format from what it is for multiple coupons.
You should talk to your server guys and ask them to fix this. The coupon attribute needs to be an array of coupons regardless of whether there is a single coupon or multiple coupons. If there are no coupons, the coupon variable can either be undefined or an empty array.
If the server guys make this change for you, your UI code should work as is.
I understand, sometimes, it can be hard to get the server guys to comply with your request in a timely fashion, especially if they are on a different team.
If this is the case, you can put in a minor patch on the UI code to get the UI working with the existing service, until the server guys come up with a fix. You will have to change your $http.get snippet like below (Also incorporating the .success to .then change suggested by #Claies):
$http.get('rest/CompanyService/getAllCoupon').then(
function(response) {
if(!response.coupon) {
// No Coupons
$scope.allCoupons = [];
} else if(response.coupon instanceof Array) {
// Multiple Coupons
$scope.allCoupons = response.coupon;
} else {
// Single Coupon
$scope.allCoupons = [response.coupon];
}
});
Note: This fix is only a temporary solution. The server code has to be fixed eventually. There is absolutely no justification for the server to send the response in different formats.