Angular 8 to 9 upgrade material index do not work as expected - angular8

having issues with <div *ngFor="let A of ANY; let t = index">
then using the t index <div *ngIf="prodT[t]"> generate error in angular 9 works in angular 8.

#angular\cdk\__ivy_ngcc__\fesm2015
add a try()catch() on material table.ts
ngOnDestroy() {
this._rowOutlet.viewContainer.clear();
try{
this._noDataRowOutlet.viewContainer.clear();
}catch{}
this._headerRowOutlet.viewContainer.clear();
this._footerRowOutlet.viewContainer.clear();
this._cachedRenderRowsMap.clear();
this._onDestroy.next();
this._onDestroy.complete();
if (isDataSource(this.dataSource)) {
this.dataSource.disconnect(this);
}
}

Related

VueJS unexpectedly runs a function

Hello guys specially VueJS devs theres something weird happened. Ill explain it one by one
Full video:
https://drive.google.com/file/d/1G2ksQsMQ1LB868dg29f8mm4NR_x5GycF/view?fbclid=IwAR1YmYbo3J6jHrY6PHd8E_lxA47VJSXV6G3132_uF6Or3bXv7MbnQbRvKaU
I use datatable and then i use this getDefaultPrice() to manipulate the price because the format of my price is like this ("65;75") to return the first value to PHP 65.00
then once i click the add to cart button please see image for codes the getDefaultPrice() also executed.
and I received an error "price.split is not a function" I tried to console.log the function and it really runs it without calling it in my add_to_cart();
<td>
<p>{{getDefaultPrice(product.price)}}</p>
</td>
<td>
<button
class="btn main_bg_color add_to_cart_btn" data-toggle="modal" data-target="#productModal"
#click="add_to_cart(product)"
>
<i class="fa fa-shopping-cart"></i> Add to cart
</button>
</td>
add_to_cart(product) {
this.modal_data = [];
this.modal_data.push(product)
this.modal_data[0].variation = this.modal_data[0].variation.split(';');
this.modal_data[0].price = this.modal_data[0].price.split(';');
this.modal_data[0].drinks_price = this.modal_data[0].drinks_price.split(';');
this.modal_data[0].drinks = this.modal_data[0].drinks.split(';');
},
getDefaultPrice(price) {
console.log("test")
var price_arr = price.split(";");
var default_price = parseFloat(price_arr[0]);
return "PHP " + default_price.toFixed(2);
},

Dynamically Tally Child Elements by Classname in Vue

I have a page that allows a user to drag/drop images into pre-defined DIVs, then I tally up the total value of the images based on their class name. What I am trying to do is get vue to read the values from each outer div.answer and get the class names of the child images.
My source code is:
<div
is="box-answers"
v-for="box in boxes.slice().reverse()"
v-bind:key="box.id"
v-bind:level="box.level"
v-bind:hint="box.hint"
></div>
<script>
Vue.component('box-answers', {
props: ['level','hint'],
template: '<div class="droppable answer :id="level" :title="hint"></div>'
});
new Vue({
el: '#mainapp',
data: {
boxes: [
{ id: 1, level: 'baselevel-1', hint: 'x 1' },
{ id: 2, level: 'baselevel-2', hint: 'x 20' },
{ id: 3, level: 'baselevel-3', hint: 'x 400' },
{ id: 4, level: 'baselevel-4', hint: 'x 8,000' },
{ id: 5, level: 'baselevel-5', hint: 'x 160,000' }
]
}
</script>
This converts to the follow HTML (the nested DIVs and SPANs are user-possible entries by dragging):
<div id="baselevel-5" class="droppable answer" title="x 160,000">
<div><img src="images/line.gif" alt="Five" class="imgfive"></div>
<span><img src="images/dot.gif" alt="One" class="imgone"></span>
</div>
...
<div id="baselevel-1" class="droppable answer" title="x 1">
<span><img src="images/line.gif" alt="One" class="imgone"></span>
</div>
Currently, I have jQuery/JavaScript calculating the point values using the following:
$(function(j) {
var arAnswers = Array(1);
count = 0; //
j("div.answer").each(function( idx ) {
currentId = j(this).attr('id');
ones = 0;
fives = 0;
if ( j("#" + currentId).children().length > 0 ) {
ones = j("#" + currentId).children().find("img.imgone").length * 1;
fives = j("#" + currentId).children().find("img.imgfive").length * 5;
arAnswers[count] = ones + fives; //Tally box value
count++;
}
});
});
I would like Vue to perform similar iteration and addition to return total value of ones and fives found based on the image classname.
Currently, you are approaching this problem as a pure-play DOM operation. If that is what you need then you can simply use $refs:
<!-- NOTICE ref -->
<div ref="boxAnswers"
is="box-answers"
v-for="box in boxes.slice().reverse()"
v-bind:key="box.id"
v-bind:level="box.level"
v-bind:hint="box.hint">
</div>
Inside your high-level component, you will have a function like:
function calculate() {
// NOTICE $refs
const arAnswers = this.$refs.boxAnswers.map((x) => {
// $el is the DOM element
const once = x.$el.querySelectorAll('img.imgone').length * 1;
const fives = x.$el.querySelectorAll('img.imgfive').length * 5;
return once + fives
});
return arAnswers;
}
But this is not the correct Vue way of doing things. You have to think in terms of events and data model (MVVM - don't touch DOM. DOM is just a representation of your data model). Since, you have a drag-n-drop based application, you have to listen for drag, dragstart, dragend and other drag events. For example:
<!-- NOTICE drop event -->
<div #drop="onDropEnd(box, $event)"
is="box-answers"
v-for="box in boxes.slice().reverse()"
v-bind:key="box.id"
v-bind:level="box.level"
v-bind:hint="box.hint">
</div>
Your onDropEnd event handler will look like:
function onDrop(box, $event) {
// box - on which box drop is happening
// $event.data - which image is being dropped
// Verify $event.data is actually the image you are intending
if ($event.data === 'some-type-image') {
// Do the counting manipulations here
// ... remaining code
}
}
This is not a complete code as I don't know other components. But it should help you with the required direction.

angular5-data-table error with paging and sorting

I am using angular5-data-table with my angular 5 application.(https://www.npmjs.com/package/angular5-data-table)
This is my code
<div class="col-md-12">
<data-table id="my-table"
title = "Test Table"
[items] = "testData"
[itemCount] = "testCount"
[expandableRows]="true"
[substituteRows]="false"
[sortAsc]="true"
[limit]=10
>
<data-table-column
[property]="'name'"
[header]="'Name'"
[sortable]="true">
</data-table-column>
<data-table-column
[property]="'age'"
[header]="'Age'"
[sortable]="true">
</data-table-column>
</data-table>
</div>
This is my output
Here i set rows limit as 10. But it showing all the data. In the bottom of the table Result is saying '1 to 10 of 12' but it's showing all the rows. Also it's not supporting with sorting.
Angular CLI: 1.7.4
Node: 8.11.1
OS: win32 x64
Angular: 5.2.10
Handle reload event in your data-table
In your HTML
<data-table (reload)="reloadItems($event)">
In your component
reloadItems(params){
if(!this.tableResource) return;
this.tableResource.query(params).then(items => this.items = items);
}

Unselect effect Radio Material2 Angular 5

I'm using mat-radio-button(material2) and I have something like a quiz. When I select an answer and go to the next quiz, the visual effect of unselect is showing in the second quiz. This happens if the selected option in the first quiz, appears in the second too, in the same position or after.
I made a simple example. You can reproduce it selecting "aa", then click ">>" button.
HTML
<mat-radio-group class="example-radio-group" [(ngModel)]="radioSelected">
<mat-radio-button *ngFor="let option of tempSublist" [value]="option" class="example-radio-button" color="primary">
{{option}}
</mat-radio-button>
</mat-radio-group>
<hr>
<button (click)="prev()"><<</button>
<button (click)="next()">>></button>
Typescript
list = [
['aa','bb','cc'],
['cc','aa','bb'],
['bb','cc','ee'],
['dd','bb','cc'],
];
index = 0;
tempSublist = this.list[this.index];
radioSelected:string;
next(){
if(this.index < this.list.length){
this.radioSelected = null;
this.index++;
this.tempSublist = this.list[this.index];
}
}
prev(){
if(this.index >= 1){
this.radioSelected = null;
this.index--;
this.tempSublist = this.list[this.index];
}
}
https://stackblitz.com/edit/angular-7s9qvs?file=app%2Fradio-ng-model-example.html
How can I solve this?
Adding trackBy option on ngFor helps to reduce the transition between the two states. Also disabling repples with [disableRipple]="true" seems to reduce the visual effect:
HTML
<mat-radio-button [disableRipple]="true" *ngFor="let option of tempSublist;
trackBy: trackByFn" ...>
...
Typescript
next() {
if (this.index < this.list.length - 1) {
//add this ^
...
trackByFn(index, item) {
return index;
}
I thought adding a control on navigation buttons would be nice:
<button [disabled]="index <= 0" (click)="prev()"><<</button>
^- this
<button [disabled]="index === tempSublist.length" (click)="next()">>></button>
^- this
Demo
If this is not enough, in last recourse, hide and show the whole block.
Wrap it in a div and set ngIf:
<div *ngIf="isVisible">
<mat-radio-group class="example-radio-group" [(ngModel)]="radioSelected">
...
and use timeout in the class on button click:
next() {
isVisible = true;
this.isVisible = false;
if (this.index < this.list.length - 1) {
...
}
setTimeout(() => this.isVisible = true, 30)
}
Demo

Vue v-for changing from version 1 to version 2

I'm learning Vue.js and found this fiddle that does exactly what I want to do.
Here is the fiddle: https://jsfiddle.net/os7hp1cy/48/
I integrated this and am getting this error:
invalid expression: v-for="user in users | filterBy searchKey | paginate"
So I've done some digging and I see it has changed from version 1 to 2. However, I don't know how to fix this.
<li v-for="user in users | filterBy searchKey | paginate">{{ user.name }}</li>
I would like to replace this with something that Vue 2 will support and will work the same way.
As of Vue version 2, filters can only be used inside text interpolations ({{ }} tags). See the documentation for migrating from Vue version 1.
You can use a computed property to filter the users and use that computed property in the v-for directive instead:
computed: {
filteredUsers: function() {
let key = this.searchKey.toUpperCase();
return this.users.filter((user) => {
return user.name.toUpperCase().indexOf(key) !== -1
})
},
paginatedUsers: function() {
var list = this.filteredUsers;
this.resultCount = list.length
if (this.currentPage >= this.totalPages) {
this.currentPage = this.totalPages
}
var index = this.currentPage * this.itemsPerPage
return list.slice(index - 1, index - 1 + this.itemsPerPage)
}
}
<li v-for="user in paginatedUsers">{{ user.name }}</li>
Also, when using v-for to generate a range of numbers like you do for your page numbers, Vue version to starts the index at 1 instead of 0. So, you'll need to update the logic depending on a starting index of 0 as well.
Here's a working fiddle.