Showing/Hiding Box inside ngFOR - javascript

I'm trying to show/hide boxes inside a ngFor but I'm getting an error. The first item works well, but the second one I get a undefined error.
ERROR TypeError: Cannot read property 'nativeElement' of undefined
at CardComponent.push../src/app/shared/card/card.component.ts.CardComponent.showBox (card.component.ts:78)
Main HTML
<div class="col s12 l6 xl4" *ngFor="let student of students | async; let i = index">
<app-card [student]="student" [i]="i"></app-card>
</div>
card component HTML
<div class="card card-min">
<div class="card-content no-padding">
<!-- HEADER -->
<div class="card-header">
<div class="col s12 no-padding">
<div class="card travel-info col s12 no-padding" style="top:0!important; left:0!important; display: none;"
#travelInfoBox>
<p>{{ i }}</p>
</div>
<div class="col s12 m6 l6 no-padding" (click)="showBox(student.studentID, i)">
<div class="arr-dep-btn-outline">
<div class="icon i-outline">
<i class="material-icons small">flight_land</i>
</div>
<div class="txt">
<p class="arr-dep-flag" *ngIf="!isPast">Arrival</p>
<p class="arr-dep-flag" *ngIf="isPast">Arrived</p>
<p class="date-stamp">{{ student.dateArrival | date }}</p>
</div>
<div class="chev" *ngIf="!isPast">
<i class="material-icons small">chevron_right</i>
</div>
</div>
</div>
<div class="col s12 m6 l6 no-padding" (click)="showBox(student.studentID, i)">
<div class="arr-dep-btn-outline">
<div class="icon i-outline">
<i class="material-icons small">flight_takeoff</i>
</div>
<div class="txt">
<p class="arr-dep-flag" *ngIf="!isPast">Departure</p>
<p class="arr-dep-flag" *ngIf="isPast">Departured</p>
<p class="date-stamp">{{ student.dateDeparture | date }}</p>
</div>
<div class="chev" *ngIf="!isPast">
<i class="material-icons small">chevron_right</i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
card.component.ts
#ViewChildren('travelInfoBox') travelInfoBox: QueryList<ElementRef>;
showBox(studentID, i) {
const nel = this.travelInfoBox.toArray();
const nativeElement = nel[i].nativeElement;
nativeElement.style.display = nativeElement.style.display === 'none' || !nativeElement.style.display ? 'block' : 'none';
this.getData(studentID);
}
EDIT
card.component.ts
#ViewChild('travelInfoBox', { read: ElementRef }) private travelInfoBox: ElementRef;
showBox(studentID) {
const nativeElement = this.travelInfoBox.nativeElement;
nativeElement.style.display = nativeElement.style.display ? 'block' : 'none';
this.getData(studentID);
}
html
<div class="card travel-info col s12 no-padding" style="top:0!important; left:0!important; display: none;" #travelInfoBox>
<router-outlet></router-outlet>
</div>

Related

Get text content of all parent divs

I have dropdown list with some file names.
What I want to achieve is to find file name parents so when checkbox is checked I can get their respective values and build them into path of some sort. For example you are clicking
updates > second_folder_updates > CSD_update checkbox
on that CSD_update checbox click you can see updates/second_folder_updates/CSD_update being console logged, same goes for first update on click you will get updates/first_update in the console
my current solution it works in a way? but this returns a lot of duplicates and incorrect data
var elem = document.getElementById("AQW_update");
function getParents(elem) {
var parents = [];
while(elem.parentNode && elem.parentNode.nodeName.toLowerCase() != 'body') {
elem = elem.parentNode;
parents.push(elem.textContent);
}
return parents;
}
var abc = getParents(elem)
for(var i = 0; i < abc.length; ++i)
abc[i] = abc[i].replace(/(\r\n|\n|\r)/gm,"")
console.log(abc.toString())
$(document).ready(function () {
$('.clickFaq').click(function () {
$('.displayDir').toggle('1000');
$("i", this).toggleClass("icon-up-circled icon-down-circled");
var $data = $('.SWCheckBox:checked').val();
console.log($data)
});
$(".open").hide();
$('.dirTitle').click(function () {
$(this).next().slideToggle();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.3.1/dist/css/bootstrap.min.css" crossorigin="anonymous">
<div class="container">
<div class="row no-gutters">
<div class="col-1">
<div class="fileListIcon iconFolder"></div>
</div>
<div class="col-9">
<div class="fileListText">
<div class="dirTitle">
updates
<i class=" .displayDir "></i>
</div>
<div class="faqQuestionsTextPreview open" style="display: none;">
<ul>
<div class="row no-gutters">
<div class="col-1">
<div class="fileListIcon iconFolder"></div>
</div>
<div class="col-9">
<div class="fileListText">
<div class="dirTitle">
first_update
<i class=" .displayDir "></i>
</div>
</div>
</div>
<div class="col-2 d-flex justify-content-center">
<div class="fileListChx ">
<input type="checkbox">
</div>
</div>
</div>
<div class="row no-gutters">
<div class="col-1">
<div class="fileListIcon iconFolder"></div>
</div>
<div class="col-9">
<div class="fileListText">
<div class="dirTitle">
second_folder_updates
<i class=" .displayDir "></i>
</div>
<div class="faqQuestionsTextPreview open" style="display: none;">
<ul>
<div class="row no-gutters">
<div class="col-1">
<div class="fileListIcon iconFolder"></div>
</div>
<div class="col-9">
<div class="fileListText">
<div class="dirTitle">
AQW_update
<i class=" .displayDir "></i>
</div>
</div>
</div>
<div class="col-2 d-flex justify-content-center">
<div class="fileListChx ">
<input type="checkbox" >
</div>
</div>
</div>
<div class="row no-gutters">
<div class="col-1">
<div class="fileListIcon iconFolder"></div>
</div>
<div class="col-9">
<div class="fileListText">
<div class="dirTitle">
CSD_update
<i class=" .displayDir "></i>
</div>
</div>
</div>
<div class="col-2 d-flex justify-content-center">
<div class="fileListChx ">
<input type="checkbox">
</div>
</div>
</div>
</ul>
</div>
</div>
</div>
<div class="col-2 d-flex justify-content-center">
<div class="fileListChx ">
<input type="checkbox">
</div>
</div>
</div>
</ul>
</div>
</div>
</div>
<div class="col-2 d-flex justify-content-center">
<div class="fileListChx ">
<input type="checkbox">
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#4.3.1/dist/js/bootstrap.min.js"
crossorigin="anonymous"></script>

How to know the selected card style and pass the value to the backend

I want to get the value in a single card selected by the user and post it to the backend
<div class="card-body">
<div class="swiper-container swipercards">
<div class="swiper-wrapper pb-4">
<div class="swiper-slide ">
<div class="card border-0 bg-default text-white">
<div class="card-header">
<div class="row">
<div class="col-auto">
<i class="material-icons vm text-template">credit_card</i>
</div>
<div class="col pl-0">
<h6 class="mb-1">Visa</h6>
</div>
</div>
</div>
<div class="card-body">
<h5 class="mb-0 mt-3">4444 5264 2541 26651</h5>
</div>
<div class="card-footer">
<div class="row">
<div class="col">
<p class="mb-0">26/21</p>
<p class="small ">Expiry date</p>
</div>
<div class="col-auto align-self-center text-right">
<p class="mb-0">Agnish Carvan</p>
<p class="small">Card Holder</p>
</div>
</div>
</div>
</div>
</div>
<div class="swiper-slide ">
<div class="card border-0 bg-warning text-white">
<div class="card-header">
<div class="row">
<div class="col-auto">
<i class="material-icons vm text-template">credit_card</i>
</div>
<div class="col pl-0">
<h6 class="mb-1">Maestro</h6>
</div>
</div>
</div>
<div class="card-body">
<h5 class="mb-0 mt-3">4444 5264 2541 26651</h5>
</div>
<div class="card-footer">
<div class="row">
<div class="col">
<p class="mb-0">26/21</p>
<p class="small ">Expiry date</p>
</div>
<div class="col-auto align-self-center text-right">
<p class="mb-0">Agnish Carvan</p>
<p class="small">Card Holder</p>
</div>
</div>
</div>
</div>
</div>
Welcome AegisFor. It looks like you're using Swiper.js?
According to the docs, under events, here is how you determine the selected item in the carousel:
const swiper = new Swiper('.swiper', {
// ...
});
swiper.on('slideChange', function () {
console.log('slide changed', swiper.activeIndex);
});
https://swiperjs.com/swiper-api#events
You could get the values by referring to the slide's attributes, like this:
....
<div class="swiper-wrapper pb-4" >
<div class="swiper-slide " id="card-1" data-card-number="12345">
....
When you change slides, refer to the div that matches the activeIndex of the carousel:
var activeCard = document.getElementById("card-" + swiper.activeIndex);
Now you can get the card number:
var cardNumber = activeCard.getAttribute("data-card-number")
How you send it to your backend depends on what backed you have. You might do something similar to this:
fetch('http://example.com/card?card-number=' + cardNumber)
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(myJson);
});
The documentation at https://swiperjs.com/swiper-api is quite good. Remember to read the docs thoroughly before posting to SO.

View not updated after modifying the array data in angular 6

I am deleting data from array and trying to update the view but it is not working.
async deleteProduct(e) {
try {
const data = await this.rest.get(environment.apiUrl + `/api/seller/products/delete/?id=${e.target.id}`);
data['success'] ? this.products = (this.products.filter(e => e != (data['products'].id))) : this.data.error(data['message']);
} catch (error) {
this.data.error(error['message']);
}
}
Html:
<section id="myProducts">
<div class="container p-5">
<app-message></app-message>
<div *ngIf="!products" class="m-auto">
<h1 class="text-center display-3 mt-5">
<i class="fa fa-spinner fa-spin"></i>
</h1>
</div>
<h3 *ngIf="products && !products.length" class="display-2 text-center mt-5">My Products is Empty</h3>
<div *ngIf="products && products.length" class="row">
<div class="col">
<h4 class="display-4">My Products</h4>
<div class="row">
<div class="offset-10 col-2 d-none d-md-block">
<p>
<small class="text-muted">Price</small>
</p>
</div>
</div>
<hr class="mt-0">
<div *ngFor="let product of products" class="product">
<div class="row">
<div class="col-4 col-md-2">
<a routerLink="/product/{{ product.id }}">
<img src="{{ product.image }}" alt="image" class="img-fluid img-thumbnail">
</a>
</div>
<div class="col-5 col-md-8">
<h5>
<a routerLink="/product/{{ product.id }}">{{ product.title }}</a>
<p class="m-0">
<small class="text-muted">{{ product.category.name }}</small>
</p>
</h5>
</div>
<div class="col-2">
<h6 class="font-weight-bold text-danger" >{{ product.price | currency : 'INR' }}</h6>
</div>
<div class="col-2">
<button type="button" class="btn btn-info" id="{{product.id}}" (click)="editProduct($event)" [disabled]="btnDisabled">Edit</button>
</div>
<div class="col-2">
<button type="button" class="btn btn-info" id="{{product.id}}" (click)="deleteProduct($event)" [disabled]="btnDisabled">Delete</button>
</div>
</div>
<hr>
</div>
</div>
</div>
</div>
</section>
After deleting the item from array, I am trying to update the object like this:
this.products = (this.products.filter(e => e != (data['products'].id)))
It seems so that your view does not check the changes of your products array.
So I would say trigger it manually:
InjectChangeDetectorRef to trigger change detection manually.
constructor(private cd: ChangeDetectorRef){....}
And in your method call this.cd.detectChanges():
async deleteProduct(e) {
...
data['success'] ? this.products = (this.products.filter(e => e != (data['products'].id))) : this.data.error(data['message']);
this.cd.detectChanges();
...
}
you are comparing e to != e['products'].id ..
it is not true.
i think you should be checking the variable which holds the id in your "e"
which means
e.id != ...or something like so.
I Hope it is working.

How to display product every 4 cols of materialize?

I have product that I want to display in every four cols of materialize. How can I achieve that task using ng-repeat?
Content of main.html:
<div class="row">
<div class="col s12 m4">
<div class="card blue-grey darken-1" ng-repeat="laptop in data">
<div class="card-content white-text">
<span class="card-title">{{laptop.name}}</span>
</div>
<div class="card-action">
{{laptop.Brand}}
</div>
</div>
</div>
</div>
Just put the ng-repeat on the col instead of the row..
<div class="row">
<div class="col s12 m4" ng-repeat="laptop in data">
<div class="card blue-grey darken-1">
<div class="card-content white-text">
<span class="card-title">{{laptop.name}}</span>
</div>
<div class="card-action">
{{laptop.Brand}}
</div>
</div>
</div>
</div>
Example: http://www.codeply.com/go/3rRmpU0NC3

Show / Hide Nested Divs inside ng-repeat

I have a div with sub divs to create a nested grid system.
There are three levels in total:
MainDiv - Always Visible
SecondDiv - Show or hide when clicked on MainDiv
ThirdDiv - Show or hide when clicked on SecondDiv
<div class="container padding" style="background-color: #fff;" ng-controller="MyCtrl">
<div class="row">
<div class="col col-75" >
Department / Product Type
</div>
<div class="col col-25">
Qty
</div>
</div>
<div ng-repeat="item in departments | orderBy:'-qty'" style="padding:0px;margin: 0;">
<div class="row" ng-class-odd="'odd'" ng-class-even="'even'">
<div class="col col-75" style="padding:0;margin:0;">
{{item.departmentName}} - {{item.productTypeName}} - Need Click here
</div>
<div class="col col-25" align="center" valign="middle" style="font-size: 14px;font-weight:bold;padding:0;margin:0;">
{{item.qty}}
</div>
</div>
<div ng-repeat="style in item.styles" style="padding:0;margin: 0;">
<div class="row">
<div class="col" style="margin-left: 5% !important;border-top-width:0;border-bottom-width:0;">
{{style.styleNum}} ({{style.qty}}) - Need Click here
</div>
</div>
<div class="row" ng-attr-id="{{ 'level-2-' + $index }}">
<div class="col col-5" style="border:0"></div>
<div class="col col-5" style="border-left:0;border-bottom:0;border-right:0;"></div>
<div class="col col-25">Color</div>
<div class="col col-25">Size</div>
<div class="col">Product#</div>
</div>
<div ng-repeat="styleLine in style.details">
<div class="row">
<div class="col col-10" style="border:0;"></div>
<div class="col col-25">{{styleLine.color}}</div>
<div class="col col-25">{{styleLine.size}}</div>
<div class="col">{{styleLine.productNum}}</div>
</div>
</div>
</div>
</div>
</div>
Now I need to add a click event on the div to show hide the necessary nested divs.
Plunker: http://plnkr.co/z3RiV6cDFC6YjrbuqxN9
Generic example using ng-init and ng-click:
<div ng-repeat="obj in items" ng-init="show = false">
<div ng-click="show = !show"></div>
<div ng-repeat="sub in obj.children" ng-show="show">
<p>Hello World!</p>
</div>
</div>

Categories

Resources