Angular5 animated progress bar - html

I have started learning angular 5 two weeks ago and I want to practice on html event. Previously I used jquery for years so I need a little help.
What i want to do can be divided in two steps:
1) animate a progress bar from 0 to a n value between 0 and 100;
2) execute the method of point 1 when the progress bar appears on screen after scrolling.
I spent my morning searching a solution but I didn't find anything. Can someone help me?
Thanks

I suggest installing ngx-bootstrap and ngx-scroll-event via npm. Then play around with the settings and numbers until your liking. I'll provide what I got from just playing around with some of the stuff.
app.component.ts
import { Component } from '#angular/core';
import { ProgressbarConfig } from 'ngx-bootstrap/progressbar';
import { ScrollEvent } from 'ngx-scroll-event';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [{ provide: ProgressbarConfig, useFactory: getProgressbarConfig }]
})
export class AppComponent {
public max = 100;
public progress = 20;
public changeProgress(event: ScrollEvent, value: number, current: number): void {
this.progress = value;
}
}
export function getProgressbarConfig(): ProgressbarConfig {
return Object.assign(new ProgressbarConfig(), { animate: true, striped: true max: 100 });
}
app.componenet.html
<div style="height:1000px"></div>
<div style="height: 500px" detect-scroll (onScroll)="changeProgress($event, 70, progress)" [bottomOffset]="200" [topOffset]="200">
<div class="mb-2">
<progressbar class="progress-striped active" [value]="progress" [max]="100" type="success"> {{progress}} / {{max}}</progressbar>
</div>
</div>
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppComponent } from './app.component';
import { ProgressbarModule } from 'ngx-bootstrap/progressbar';
import { ScrollEventModule } from 'ngx-scroll-event';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
ScrollEventModule,
ProgressbarModule.forRoot()
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

Related

TypeScript variable seems not to load the value from one file to another

I am following the tutorial here: https://coursetro.com/posts/code/154/Angular-6-Tutorial---Learn-Angular-6-in-this-Crash-Course
I currently have the code up to the section titled Fetching More Data from the API working. In short this is supposed to make a page with a bunch of users accessed through a toy API. The users are listed on a page with some personal information, and each one links to a very basic profile page displaying their details. Up to the section I mentioned above, I am successfully interfacing with the API, getting the users and displaying them and some personal information on the main page.
However, the code in this section is intended to collect an individual user's details and display them on a linked page. In trying to follow the example, my code does produce a page with the right outlines, but the value of the variable user$ and its fields like user$.name don't seem to be loaded by the details component. Where those values are supposed to show up, it's blank.
The app files:
app-routing.module.ts
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { UsersComponent } from './users/users.component';
import { DetailsComponent } from './details/details.component';
import { PostsComponent } from './posts/posts.component';
const routes: Routes = [
{
path: '',
component: UsersComponent
},
{
path: 'details/:id',
component: DetailsComponent
},
{
path: 'posts',
component: PostsComponent
}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
app.component.html
<div id="container">
<app-sidebar></app-sidebar>
<div id="content">
<router-outlet></router-outlet>
</div>
</div>
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { SidebarComponent } from './sidebar/sidebar.component';
import { PostsComponent } from './posts/posts.component';
import { UsersComponent } from './users/users.component';
import { DetailsComponent } from './details/details.component';
import { HttpClientModule } from '#angular/common/http';
#NgModule({
declarations: [
AppComponent,
SidebarComponent,
PostsComponent,
UsersComponent,
DetailsComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
data.service.ts
import { Injectable } from '#angular/core';
import {HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class DataService {
constructor(private http: HttpClient) { }
getUsers() {
return this.http.get('https://jsonplaceholder.typicode.com/users')
}
getUser(userId) {
return this.http.get('https://jsonplaceholder.typicode.com/users'+userId)
}
getPosts() {
return this.http.get('https://jsonplaceholder.typicode.com/posts')
}
}
users files:
users.component.html
<h1>Users</h1>
<ul>
<li *ngFor="let user of users$">
{{user.name}}
<ul>
<li>{{user.email}}</li>
<li>{{user.website}}</li>
</ul>
</li>
</ul>
users.component.ts
import { Component, OnInit } from '#angular/core';
import { DataService } from '../data.service';
import { Observable } from 'rxjs';
#Component({
selector: 'app-users',
templateUrl: './users.component.html',
styleUrls: ['./users.component.scss']
})
export class UsersComponent implements OnInit {
users$: Object;
constructor(private data: DataService) { }
ngOnInit() {
this.data.getUsers().subscribe(
data => this.users$ = data
);
}
}
details files:
details.component.html
<h1>{{ user$.name }}</h1>
<ul>
<li><strong>Username: </strong> {{user$.username}}</li>
<li><strong>Email: </strong> {{user$.email}}</li>
<li><strong>Phone: </strong> {{user$.phone}}</li>
</ul>
details.component.ts
import { Component, OnInit } from '#angular/core';
import { DataService } from '../data.service';
import { Observable } from 'rxjs';
import { ActivatedRoute } from '#angular/router';
#Component({
selector: 'app-details',
templateUrl: './details.component.html',
styleUrls: ['./details.component.scss']
})
export class DetailsComponent implements OnInit {
user$: Object;
constructor(private data: DataService, private route: ActivatedRoute) {
this.route.params.subscribe( params => this.user$ = params.id );
console.log(this.route.params);
}
ngOnInit() {
this.data.getUser(this.user$).subscribe(
data => this.user$ = data
);
}
}
I tried logging values to the console, but I don't fully understand how TypeScript works so I don't fully know what I really should expect from these logs. In any case, in the log that I made in the details TypeScript file, it showed an object with no apparent loading errors.
this.route.params is a Observable. I am not sure what you can get by logging it.
I would suggest you add a log when subscribing to a observable and see what kind of data you really get. Like.
this.data.getUser(this.user$).subscribe(
data => {console.log(data);this.user$ = data}
);
#Adem, As Haijin comment, you must "work" a bit in subscribe parameter. The idea is that you subscribe to get the parameter, and, when you have the parameter, you ask about the user. But you need to make in the same step using switchMap
ngOnInit()
{
//You subscribe the param. When you have ask for the user
this.route.params.subscribe( params =>
{
this.user$ = params.id;
//In subscribe you ask for the user
this.data.getUser(this.user$).subscribe(
data => this.user$ = data
)
});
}
Well, really In Angular is better don't subscribe two times else using Rjxs and switchMap
ngOnInit()
{
//You subscribe the params, but you don't want the param
this.route.params.pipe(
switchMap(params =>
{ //you want return the user
return this.data.getUser(params.id)
})
).subscribe(data => this.user$ = data)
}

Angular 4 - service data is not persistent

I am having some trouble figuring out where I went wrong and would really appreciate some help with this.
I have a component: AudioComponent, which captures an html5 tag as a #ViewChild, then registers itself with a service: AudioService.
Here is the AudioComponent:
/* audio.component.ts */
import { Component, OnInit, Input, ViewChild } from '#angular/core';
import { IAudioOptions } from './audio-options';
export const defaultOptions: IAudioOptions = {
controls: true,
autoplay: false,
loop: false,
volume: 1.0,
startPosition: 0.0,
preload: "metadata",
muted: false
};
#Component({
selector: 'ng-audio',
templateUrl: './audio.component.html',
styleUrls: ['./audio.component.css']
})
export class AudioComponent implements OnInit {
#Input() src: any;
#Input() options: any = defaultOptions;
#Input() register: any;
#ViewChild('audio') player: any;
constructor() { }
ngOnInit() {
if (this.register) {
console.log("registering");
console.log(this.register(this));
}
}
play() {
this.player.nativeElement.play();
}
}
And the AudioService:
/* audio.service.ts */
import { Injectable } from '#angular/core';
import { AudioComponent } from './audio/audio.component';
#Injectable()
export class AudioService {
private players: AudioComponent[];
constructor() { }
register(player: AudioComponent) {
console.log("player registered");
if (this.players) {
this.players.push(player);
}
else {
console.log("initializing service");
this.players = [];
this.players.push(player);
}
return this.players;
}
getPlayers(): string[] {
var out: string[];
for (let i = 0; i < this.players.length; i++) {
out.push(this.players[i].src);
}
return out;
}
}
I'm instantiating two of the ng-audio components in my app.component.html file:
<!-- register refers to the AudioService.register function -->
<ng-audio [src]="src" [register]="register"></ng-audio>
<ng-audio [src]="src2" [register]="register"></ng-audio>
And the audio players themselves appear when I load the page.
What's puzzling is that I get the following logged to the console:
- registering
- player registered
- initializing service
- [AudioComponent]
- registering
- player registered
- initializing service // <- this should only happen the first time!
- [AudioComponent] // <- and this should now contain two elements!
For some reason, the players: AudioComponent[] property of the AudioService does not persist. So each time register() is called, it's like I'm calling it on a completely new AudioService instance!
Again, any help will be greatly appreciated. I'll be posting updates if I can figure this out.
EDIT: I've included my app.module.ts and app.component.ts files in case there's something I missed setting up the service as a provider.
AppModule:
/* app.module.ts */
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppComponent } from './app.component';
import { AudioComponent } from './audio/audio.component';
import { AudioService } from './audio.service';
#NgModule({
declarations: [
AppComponent,
AudioComponent
],
imports: [
BrowserModule
],
exports: [AudioComponent],
providers: [AudioService],
bootstrap: [AppComponent]
})
export class AppModule { }
And AppComponent:
/* app.component.ts */
import { Component } from '#angular/core';
import { AudioComponent } from './audio/audio.component';
import { AudioService } from './audio.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
src = 'http://url.to/file.mp3';
src2 = 'http://url.to/another-file.mp3';
interval: any;
player: AudioComponent;
register: any;
play: any;
constructor(
private service: AudioService
) {
this.register = this.service.register;
this.play = this.service.getPlayers;
}
}

Route navigation in Angular4 not reacting

I have made an Angular4 component and the page that it generates has a button to navigate to another page. I don't get any errors and the pageUrl changes but the content of the page stays the same.
Here is my code:
app.component.ts
import { Component } from '#angular/core';
import { Router } from "#angular/router";
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(private router: Router){}
username = "";
password = "";
log = function () {
if (this.username != "" && this.password != "") {
console.log(this.username + " " + this.password);
this.router.navigate(['/dashboard']);
}
}
}
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { RouterModule } from '#angular/router';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { AppComponent } from './app.component';
import { DashboardComponent } from './dashboard/dashboard.component';
#NgModule({
declarations: [
AppComponent,
DashboardComponent,
],
imports: [
BrowserModule,
FormsModule,
RouterModule.forRoot([
{
path: 'dashboard',
component: DashboardComponent
}
]
)
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {
}
app.component.html
<div class="outer-container">
<div class="inner-container">
<div class="centered-content">
<div class="center"><img src="../favicon.png"></div>
<label class="addText"> Username: </label><input [(ngModel)]
="username" class="addText"><br>
<label class="addText"> Password: </label><input [(ngModel)]
="password" type="password" class="addText"><br>
<div class="center"><button (click) ="log()">Log in</button></div>
</div>
</div>
</div>
To achieve what you want, have the app.component only to include the router-outlet:
#Component({
selector: 'app-root',
template: `
<!-- Views go here-->
<router-outlet></router-outlet>
`,
})
export class AppComponent { }
And then have a separate component for each view you want. So in your case you'd want to create a LoginComponent, which would then route to the DashboardComponent from there.
PS Of course this is expandable and you could add a header component tag in the AppComponent html, or whatever else and so on and so on. But just to showcase this simple use case.
you need to specify where to display the DashboardComponent
add this tag to tell angular the location where to display the component results from router
<router-outlet></router-outlet>

how to implement ng2-dragula in angular 2

how to implement ng2-dragula in angular 2.
My code is shared below,
****viewer.component.ts****
import { Component, Input, Output, EventEmitter } from '#angular/core';
import { Injectable } from '#angular/core';
import { Headers, Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx';
import { ImageViewerService } from '../services/http.services';
import { Dragula,DragulaService } from 'ng2-dragula/ng2-dragula';
#Component({
moduleId: module.id,
selector: 'viewer',
directives: [Dragula],
viewProviders: [DragulaService],
providers: [ImageViewerService, DragulaService],
templateUrl: 'viewer.component.html',
})
export class ViewerComponent {
#Output() click = new EventEmitter();
http: Http;
url: string;
obj: any;
getData: string;
postData: string;
users: any;
firtsImageToBind: any;
tile: number;
tableVisible: boolean;
status: { isopen: boolean } = { isopen: false };
localImageViewerService: ImageViewerService;
localDragulaService: DragulaService;
constructor(http: Http, imageViewerService: ImageViewerService,
localDragulaService: DragulaService) {
this.users = [1];
this.http = http;
this.localImageViewerService = imageViewerService;
this.localDragulaService = localDragulaService;
this.imageReceivedFromWebAPI();
}
Ok so a quick example showing how to implement dragula into Angular2 project first install via npm:
npm install ng2-dragula dragula --save
Next import into module:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import { AppComponent } from './app.component';
import {DragulaModule} from 'ng2-dragula/ng2-dragula'; // Here
#NgModule({
declarations: [
AppComponent
],
imports: [
DragulaModule, // Here
BrowserModule,
FormsModule,
HttpModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Inside app.component.html you do this.
<div>
<div class='wrapper'>
<div class='container' [dragula]='"first-bag"'>
<div>You can move these elements between these two containers</div>
<div>Moving them anywhere else isn't quite possible</div>
<div>There's also the possibility of moving elements around in the same container, changing their position</div>
</div>
<div class='container' [dragula]='"first-bag"'>
<div>This is the default use case. You only need to specify the containers you want to use</div>
<div>More interactive use cases lie ahead</div>
<div>Make sure to check out the <a href='https://github.com/bevacqua/dragula#readme'>documentation on GitHub!</a></div>
</div>
</div>
</div>
run the project, and you'll be able to drag the text up and down i.e changing its order.
Example specified above is from dragula github page.

Can't I use a component defined in a file other than app.component.ts in HTML directly?

I am facing difficulty in using a component defined in a file named navigation.component.ts directly on HTML Page.
The same component works fine if I use it under template of a component defined on app.component.ts.
Contents of app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { AppComponent } from './app.component';
import { NavigationComponent} from './shared/navigation.component';
#NgModule({
imports: [BrowserModule],
declarations: [AppComponent, NavigationComponent],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Contents of navigation.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'navigation',
templateUrl: '/views/shared/navigation.html'
})
export class NavigationComponent {
userName: string = 'Anonymous';
}
Contents of app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'main-app',
template: '<navigation></navigation><h1>{{pageTitle}}</h1>'
})
export class AppComponent {
pageTitle: string = 'Portal 2.0';
}
Contents of index.html
<body>
<main-app></main-app>
</body>
The above works and renders menus on top but when I try to use <navigation> directly (given below) it doesn't render it, doesn't show any errors either.
<body>
<navigation></navigation>
</body>
Am I doing something wrong?
And the bigger question is how I go debugging issues like this?
Yes you can use web components. Add all the components that you want to load to entrycomponents.
Using createCustomElement you can create elements and use their selector anywhere.
import { BrowserModule } from '#angular/platform-browser';
import { NgModule, Injector } from '#angular/core';
import { createCustomElement } from '#angular/elements';
import { AppComponent } from './app.component';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [],
entryComponents: [AppComponent]
})
export class AppModule {
constructor(private injector: Injector) {
console.log('Elements is loaded: Activation');
this.registerComponent('metro-activation-loader', AppComponent);
}
public ngDoBootstrap(): void {
console.log('Elements is loaded: Activation ngDoBootstrap');
}
// tslint:disable-next-line:no-any
private registerComponent(name: string, component: any): void {
const injector = this.injector;
const customElement = createCustomElement(component, { injector });
customElements.define(name, customElement);
}
}