Can we combine lightbox-gallery with onLogin-adding data(pictures) with angular 6 on firebase? - angular

my firebase database> I want to get data from my firebase to my lightbox-gallery to make it
work. Because I'm posting data(images) from firebase to other page and
need to link the source of lightbox-gallery with my firebase somehow. Also
how can I make an infinite loop through my firebase? Right now my
lightbox-gallery getting images from folder 'kuhinje' into the project.
Can someone help me, please?
I have tried to put "const src = this.db.list(/kuhinje) + i +
'.jpg';" but it won't work because of this part (" + i + '.jpg' ")**
> Component.ts
export class KuhinjeComponent implements OnInit, OnChanges {
images:Observable<GalleryImage[]>;
//lightbox-gallery
public albums: Array;
private _subscription: Subscription;
this.albums = [];
for (let i = 1; i <= 50; i++) { //how to make loop infinite?
const src = '../../assets/slike/kuhinje/image' + i + '.jpg'; //want to change this source to my firebase database
const caption = 'Image ' + i + ' caption here';
const thumb = 'demo/img/image' + i + '-thumb.jpg';
const album = {
src: src,
caption: caption,
thumb: thumb
};
this.albums.push(album);
}
}
<h2>Kuhinje</h2>
<div >
<ul>
<li *ngFor="let image of images | async"> //lightbox loop
<a [routerLink]="['/image', image.$key]">
<img src="{{ image.url }}" (click)="open(i)"/>
</a>
</li>
</ul>
</div>

Related

unable to iterate over an array within my html

I am trying to make a breadcrumb component for angular7 but I can't get my array to properly show into my HTML and would like some tips because I can't find it on the internet. if you would be so kind as to help me I am still new to angular and can't think of a better way to make a breadcrumb component.
my component.ts -
breadcrumbLists: Array <any> = [];
breadcrumburl: Array <any> = [];
constructor(private _router: Router) { }
ngOnInit() {
this.listenrouting();
}
listenrouting(): void {
let routerUrl: string, routerList: Array < any > ;
let i;
let done;
this._router.events.subscribe((router: any) => {
routerUrl = router.urlAfterRedirects;
if (routerUrl && typeof routerUrl === 'string') {
this.breadcrumbLists.length = 0;
routerList = routerUrl.slice(1).split('/');
this.breadcrumbLists = routerList;
if (done != false) {
this.breadcrumbLists.forEach(bread => {
if (i != null) {
this.breadcrumburl.push([{ name: bread }, { url: i + "/" + bread }])
} else {
this.breadcrumburl.push([{ name: bread }, { url: "/" + bread }])
}
i = "/" + bread
});
}
console.log("url", this.breadcrumburl)
console.log(this.breadcrumbLists)
done = false;
}
});
}
and then my HTML -
<nav>
<div>
<li *ngFor="let Breadcrumb of breadcrumburl">
<a routerLink="{{Breadcrumb.url}}">{{Breadcrumb.name}}</a>
</li>
</div>
</nav>
If I'm not wrong, you want to push into breadcrumburl array as -
this.breadcrumburl.push({name: bread, url: i + "/" + bread});
Currently, you created nested arrays & pushed 2 elements in all nested arrays in breadcrumburl

Filter search results react

My data back from search result has columns: enTitle,Image,url,enDescription,HasLandingPage,AddInfo.
I want to filter search results by AddInfo to show in different lists. later if I can add a button that would be better.
Render Data:
const ListArticle = (props) =>{
return (
<div className="card">
<div className="search-img-lft">
<a href={props.link} target="_blank">
<img src={props.image} alt="" />
</a>
</div>
<div className="search-imgcont-rgt">
<a href={props.link} target="_blank">
<h3>
{props.title}
{props.kind} // just to see if kind works
</h3>
<p>{props.desc}</p>
</a>
{props.link}
</div>
</div>
);
}
List Class:(ignore the i,brac & lim they are for pagination)
class List extends React.Component {
render(){
const liArt =[];
const searchText = this.props.searchText.toLowerCase().replace(/[^a-z0-9]/g, '');
var i = 0;
const brac = this.props.start;
const lim = brac + this.props.qtyPerPage;
//the filter below works for resources but I want all to be filtered and show in the list in previous code snippet
this.props.list.filter(u=>u.AddInfo == "resource").map((article)=>{
var artText = (article.enTitle + " " + article.URL + " " + article.enDescription + " " + article.AddInfo).toLowerCase().replace(/[^a-z0-9]/g, '');
if(artText.indexOf(searchText)===-1){
return;
}
i++;
if(brac<i && i<lim){
liArt.push(
<ListArticle key={article.Image+article.URL}
title={article.enTitle}
image={article.Image+"?h=100&mode=crop&scale=down"}
link={JSON.stringify(article.HasLandingPage).toUpperCase()=="TRUE" ? "/en/"+article.URL : "/" + article.URL}
desc={article.enDescription}
kind={article.AddInfo.includes("SKU") ? " Product" : (article.AddInfo.includes("resource") ? " Resource" : " Page")} />
);//push
} //limit check
});//map
return (
<div className="search-page-listbox">
{liArt}
</div>
);
}
}
If i got you right, you want to create multiple lists while each list shows items of another"AddInfo".
First, I would recommend to separate your task into three components (instead of two):
First component is the ListArticle which will be the list item,
Second will be the component List -> that will receive the list you want to show (after they have been filtered),
Last component will be ListContainer -> this one will hold multiple lists (as many as the options of AddInfo).
Then, in ListContainer you can go over all unique AddInfo, and create List component for every option - passing only filtered items:
ListArticle.js
import React from 'react';
const ListArticle = (props) =>{
return (
<div className="card">
<div className="search-img-lft">
<a href={props.link} target="_blank">
<img src={props.image} alt="" />
</a>
</div>
<div className="search-imgcont-rgt">
<a href={props.link} target="_blank">
<h3>
{props.title}
{props.kind} // just to see if kind works
</h3>
<p>{props.desc}</p>
</a>
{props.link}
</div>
</div>
);
}
export default ListArticle;
List.js
import React from 'react';
import ListArticle from './ListArticle';
export default class List extends React.Component {
render() {
return (
this.props.list.map(article => <ListArticle key={article.Image + article.URL}
title={article.enTitle}
image={article.Image + "?h=100&mode=crop&scale=down"}
link={JSON.stringify(article.HasLandingPage).toUpperCase() == "TRUE" ? "/en/" + article.URL : "/" + article.URL}
desc={article.enDescription}
kind={article.AddInfo.includes("SKU") ? " Product" : (article.AddInfo.includes("resource") ? " Resource" : " Page")} />
)
)
}
}
ListContainer.js
import React from 'react';
import List from './List';
class ListContainer extends React.Component {
constructor(props){
super(props);
}
render() {
let lists = {};
let searchText = this.props.searchText;
if(this.props){
let filteredList = this.props.list.filter(article=>(article.enTitle + " " + article.URL + " " + article.enDescription + " " + article.AddInfo).toLowerCase().replace(/[^a-z0-9]/g, '').indexOf(searchText)!==-1);
filteredList && filteredList.forEach(u => {
if(lists[u.AddInfo]===undefined) lists[u.AddInfo]=[];
lists[u.AddInfo].push(u);
});
}
return(
Object.keys(lists).map(function(key, index) {
return <List list={lists[key]} />
})
)
}
}
export default ListContainer;
Usage:
<ListContainer list={list} searchText={searchText} />
Hope it helped :)
I'd return something like this from your List class (I tried explaining my thought process in comments inside the code):
return (<React.Fragment>
{
// second (kinda), I'd convert the inside generated collection (object) into an array
// -> where the array elements are now ["AddInfo type", [array of elements with that type]]
Object.entries(
// first, convert the list into an object, collecting each type of "AddInfo" into
// -> a unique property, and storing all objects w/ that type in an array
this.props.list.reduce((output, u) => {
if (!output[u.AddInfo]) output[u.AddInfo] = [];
output[u.AddInfo].push(u);
return output
}, {})
)
// third, I'd map the new array of ["AddInfo type", [array of elements with that type]] into
// -> the jsx output you want, like this:
.map(([type, array]) => {
return <div className="search-page-listbox">
{array.map((article, i) => {
// ... everything inside your ".map((article...)" function can go here
})}
</div>
})
}
</React.Fragment>)
A few notes:
You can replace var i = 0 and i++ lines with the i index that automatically comes from the second parameter in the map function (see my version of array.map((article, i) => ...)
If you haven't seen things like array destructuring (ex: .map(([type, array]) => ...)) let me know, I can explain. It's a pretty shnazzy thing you can do to save some lines.
My first step was to figure out how to create an object container which holds sorted data based on AddInfo - that's why my // first comment comes technically after the // second comment. Hope that makes sense.
Let me know if you have questions or if there was a typeo that's breaking my code. I haven't tested it obviously since I don't have your react code / variables.

One object is displayed multiple times when its number of likes are updated in angular firebase

I'm building a like/dislike system for posts on my website. Every time the user clicks on the like button, the number of likes gets updated in the database. The object stored in the database has a URL of the image, a category and the number of likes as its keys.
Following is my code to update: likedButton(img) is a function which is called when the user clicks the like button.
likedButton(img) {
var url = img.src;
var x = this.db
.list('/userPosts', ref => ref.orderByChild('url').equalTo(url));
x.snapshotChanges().first()
.subscribe((datas) => {
var keys = datas[0]['key'];
var obj = x.valueChanges().first().subscribe((z) => {
var n: number = z[0]['likes'];
firebase.database().ref('/userPosts/' + keys).update({
'likes': n + 1
});
});
});
}
If I press the like button, one post is displayed multiple times in Angular 6.
Below is my display function:
constructor(
public db: AngularFireDatabase,
private router: Router,
public authService: AuthService
) {
db.list('/userPosts').valueChanges().subscribe(images => {
Array.prototype.push.apply(this.image, images);
this.image.reverse();
});
this.authService.af.auth.onAuthStateChanged((user) => {
if (user != null) {
this.logged = true;
this.userName = user.displayName;
}
});
}
This is the template
<ul class="images">
<li *ngFor="let image of image | imagefilter : x ">
<img #img src="{{image.url}}" [ngStyle]="{'width':'26%','height':'26%'}" [className]="'img-thumbnail'">
<button (click)="likedButton(img)" class="btn btn-primary">Like {{image.likes}}</button>
</li>
</ul>

fetch image from mongodb to website with angular6

I'm working on my website and I'd like to fetch an image from my DB to the header of my website.
I have a customer ID and every customer has an different logo. Now I don't know how to display the logo with angular.
Here is my unfinished code:
Component which get the image by customer id:
logo: string;
companyName: string;
ngOnInit() {
this.currentLang = this.translate.getDefaultLang();
this.languages = this.translate.getLangs();
this.activatedRoute.queryParams.subscribe((params: Params) => {
const customerId = params["customerId"];
if (customerId) {
this.userService.getCustomer(customerId)
.subscribe(customer => {
this.logo = customer.logo, this.companyName = customer.name
});
}
});
}
And here I'd like to display the selected logo:
<div class="logo">
<span class="logo-type"><img src="{{ customer.logo }}"></span>
</div>
Got it, it is very simple. Just write 'logo':
<div class="logo">
<span class="logo-type"><img src="{{ 'logo' }}"></span>
</div>

How to use Observables/ real-time change only one entry in table in angular2+

I am stuck with an issue in angular4 and node.js app. I display the data in a table that has 7 columns via *ngFor . Now the issue is , i need to dynamically and on real-time basis update the last column . i.e. if the column -> Active ... is Yes , then i display a green color and when the Active ...is No, then i display a red color. But then i am not sure how to update the last column and only the last column real-time.
[1]
I thought of using Observables code in init from where i call the table data, but that will only keep on showing the loader always , as the data will keep on uploading regularly after a few seconds and disturb the entire table view.
[2]
And i have shown the color based on an if condition, but in all the entries, it shows only green color.
code -
interface.component.ts
export class MasterInterfaceComponent implements OnInit {
activeCheck;
activeValue;
activeRedColor;
activeGreenColor;
ngOnInit() {
console.log("beginning of func");
Observable.interval(15000).subscribe(x => {
console.log("Called")
this.viewData();
});
}
viewData() {
this.loading = true;
var url = config.url;
var port = config.port;
this.http.post("http://" + url + ":" ...... ('Token') }) })
.map(result => this.result = result.json(),
)
.subscribe((res: Response) => {
this.loading = false;
this.records = res;
console.log("xxxx interface view result data ",this.result)
console.log("XXXXXXXXXXXX interface view res data ", res);
this.activeCheck = this.result;
for (let obj of this.activeCheck){
for (let key in obj){
if (key == "ACTIVE_YN"){
if (obj[key] == "Y"){
this.activeRedColor = false;
this.activeGreenColor = true;
console.log("this.activeGreenColor = true;");
}
else if (obj[key] == "N"){
this.activeRedColor = true;
this.activeGreenColor = false;
console.log("this.activeGreenColor = false;");
}
}
}
}
});
}
interface.component.html
<tbody>
<tr *ngFor="let data of result |filter:filter| orderBy : 'IF_ID'|
paginate: { itemsPerPage: 5, currentPage: p }; let i =
index">
<td class="text-center" style="width:8%">
<a [hidden]= "accessIdHide" [routerLink]="['/master-system/update-
interface']" (click)="forUpdate(data)" data-toggle="tooltip"
title="Update" style="color:#ffffff;;float:left"
type="link">
<span class="glyphicon glyphicon-plus-sign"></span>
</a>{{data.IF_ID}}
</td>
<td>{{data.IF_CD}}</td>
<td>{{data.IF_NAME}}</td>
<td>{{data.IF_DESCRIPTION}}</td>
<td>{{data.SRC_SYS_NAME}}</td>
<td>{{data.TRGT_SYS_NAME}}</td>
<td >
<img [hidden]= "activeGreenColor" src = "url" width="10" height =
"10">{{data.ACTIVE_YN}}
<img [hidden] = "activeRedColor" src = "url" width="10" height =
"10">{{data.ACTIVE_YN}}
</td>
</tr>
</tbody>
First of all, you do not need two switches, but the way you had it is ok, but for our discussion, let's just say we have one switch "isActive".
I think your code should work, but you need to make sure the subscription is firing, ex.
.subscribe((res: Response) => {
console.log(res);
If this code fires every time the data changes, then your img should be turned on and off
<img *ngIf="isActive" src="url">
or
<img [ngClass]="{ isActive: green }">
Either of the above is fine. So just try to debug your observable to work the way you wanted, ex. when it should be fired and in which frequency.

Resources