How to reset scroll on route changes in ember 3? - javascript

I'm trying to use hook activate, didTransition, or willTransition, but none of these work, they do nothing at all.
I try to start by one route:
// app/routes/section.js
import Route from '#ember/routing/route';
export default class SectionRoute extends Route {
...
activate() { scroll(0, 0); }
}
<!-- app/templates/section.hbs -->
<h1>{{model.title}}</h1>
<p>{{model.body}}</p>
{{outlet}}
{{#each model.subsections as |s| }}
<Section #section={{s}} />
{{/each}}
This works in my js browser console:
scroll(0, 0);
This is my router
// app/router.js
...
Router.map(function() {
this.route('docs');
this.route('section', { path: '/docs/section/:slug' });
});
If I make section a child of docs, it works, as long as I don't hide parent's content, but I want to hide it.
An anchor in link-to component could help.
When I remove this piece of css, it works.
html {
scroll-behavior: smooth;
}

Your approach is working as expected. I have created an Ember Twiddle to verify that one, which you can find here. It has two routes. One which scrolls to the top when activated and one which scrolls to bottom when activated. It's scrolling as expected.
I guess you may be facing issues with the hook if transitioning between subroutes? A route is considered to stay active and the activate hook is not called
if a transition does not change the route but only the dynamic segments or query parameters used for the route or
if a transition happens between subroutes of that route.
If you want to have scroll to top on every transition or want to have more granular control, which transitions should trigger that scrolling I would recommend to use routeDidChange event of RouterService instead.

Related

How to add ngx-loading-bar as preloader into Angular project

I have a project developed in Angular 6+, when user comes to website, first he sees logo and loading bar underneath it.
I have a problem switching to ngx-loading-bar insted of pace.js
Right now I am using Pace (the last example a fixed width line)
https://github.hubspot.com/pace/docs/welcome/
integrated into the index.html of the root project.
I want to put ngx-loading-bar instead of pace to do same job.
ngx-loading-bar is already implemented and working when adding <ngx-loading-bar></ngx-loading-bar> in some of the components but not in the index.html.
I want to put same style same width loading bar as on example link bellow (4th bullet example, similar to pace)
https://aitboudad.github.io/ngx-loading-bar/
so on the load, users sees the loading bar how it loads and on load, it goes on the next component as project example bellow.
Here is the example of project
www.wowlectures.com/pitchdeck
Not sure why you want it to work in index.html, do it in app.component.
You could create a loading service. A simple way is this:
#Injectable({providedIn: 'root'})
export class LoadingService {
private _loading = true;
get isLoading() {
return this._loading;
}
set isLoading(v: boolean) {
this._loading = v;
}
}
Then in app.component.ts:
export class AppComponent {
constructor(public loading: LoadingService) {}
}
And app.component.html:
<any-loading-component *ngIf="loading.isLoading"></any-loading-component>
<router-outlet></router-outlet>
A cleaner way is to use subjects/observables in the service and subscribe to changes where you want to show the loading-bar and dispatch from anywhere you want it to start loading.
<app-root>
<ngx-loading-bar></ngx-loading-bar>
</app-root>
hey you can add this in your index.html

Responding to a click on a Vue element programmatically

Essentially, I want my Vue instance to respond to a click on an uploaded thumbnail.
I'm using the FineUploader Vue package with the template layout per the docs (see end of the question). Upon uploading an image, a tree like this is outputted:
<Root>
<Gallery>
<Thumbnail>
</Gallery>
</Root>
Coming from a jQuery background I really have no idea about the 'correct' way to go about this given that the Thumbnail Template is defined by the package already, and so I'm not creating my own Thumbnail template. I know that I can access elements like this:
let thumb = this.$el.querySelector('.vue-fine-uploader-thumbnail');
And perhaps a listener
thumb.addEventListener('click', function() {
alert('I got clicked');
});
But dealing with the Vue instance being re-rendered etc. I'm not familiar with.
Vue Template:
<template>
<Gallery :uploader="uploader" />
</template>
<script>
import FineUploaderTraditional from 'fine-uploader-wrappers'
import Gallery from 'vue-fineuploader/gallery'
export default {
components: {
Gallery
},
data () {
const uploader = new FineUploaderTraditional({
options: {/*snip*/}
})
return {
uploader
}
}
}
</script>
In order to respond to click events you add the v-on:click (or it's short form: #click) to whatever tag you want.
If you have elements that are nested that respond to the click event you might experience that a click on a child triggers a parents click event. To prevent this you add #click.stop instead, so that it doesn't trigger the parents click.
So you would have something along the lines of:
<Gallery #click="myFunction" />

Angular sub-component style does not change until next ngAfterViewChecked

Angular version: 5.0.3
I have put my code here.
I have made a custom inkbar module, and imported it to the app. I use
<lib-inkbar [nextEle]="inkbarSubject" [color]="inkbarColor"></lib-inkbar>
...to install it in my app.component.
The inkbar under the navigation menu tabs is expected to automatically go in position where router link is currently active. (And this is done by getting the width and offset left of a given element, and move to it.) For example, at the beginning, "/index" is active, so "Index" tab has a class "active", and inkbar should translate under it.
I have achieved this by putting the code in Angular's ngAfterViewChecked life-cycle. inkbarMove() tells inkbar where to go by telling it the element (i.e. the active nav tab).
ngAfterViewChecked() {
this.navMenus = this.ul.nativeElement.children;
let actMenu = this.getAvtiveMenu();
if (actMenu) {
this.inkbarMove(actMenu);
}
}
inkbarMove = (ele: HTMLBaseElement | MouseEvent) => {
if (ele instanceof MouseEvent) {
ele = ele.target as HTMLBaseElement;
}
this.inkbarSubject.next(ele);
};
However, this works only after next ngAfterViewChecked() fires. When page first loads, the inkbar will stay {width: 0px; left: 0px} style, as initial default value, no matter how many times I tell it to "Move" (I even wrote a for-loop, which made my browser crash, but still didn't work lol). It will only starts to move after I press the button and manually call ngAfterViewChecked() again.
Does someone know what is going on here?

Scroll to a certain element of the current page in Angular 4

Upon clicking a button (which is bottom of the page), I want to go to a certain element (in my case, #navbar) which is in the top of the current page, but I don't know how to do it. I've tried the following code with no avail.
<nav class="navbar navbar-light bg-faded" id="navbar">
<a class="navbar-brand" href="#">
{{appTitle}}
</a>
<!-- rest of the nav link -->
</nav>
<!-- rest of the page content -->
<!-- bottom of the page -->
<button class="btn btn-outline-secondary" (click)="gotoTop()">Top</button>
In angular component:
import { Router } from '#angular/router';
/* rest of the import statements */
export class MyComponent {
/* rest of the component code */
gotoTop(){
this.router.navigate([], { fragment: 'navbar' });
}
}
I would really appreciate if someone helped me out with a solution and explained why my code hadn't worked.
Please note that element (navbar) is in other component.
You can do this with javascript:
gotoTop() {
let el = document.getElementById('navbar');
el.scrollTop = el.scrollHeight;
}
This will bring the DOM element with id="navbar" into view when the method is called. There's also the option of using Element.scrollIntoView. This can provide a smooth animation and looks nice, but isn't supported on older browsers.
If the element is in a different component you can reference it several different ways as seen in this question.
The easiest method for your case would likely be:
import { ElementRef } from '#angular/core'; // at the top of component.ts
constructor(myElement: ElementRef) { ... } // in your export class MyComponent block
and finally
gotoTop() {
let el = this.myElement.nativeElement.querySelector('nav');
el.scrollIntoView();
}
Working plunker.
I know, you want to scroll to a specific element in the page. But, if the element is in the top of the page, then you can use the following:
window.scrollTo(0, 0);
document.getElementById("YOUR_DIV_ID").scrollIntoView({ behavior: 'smooth' });
I think your way didn't work because of the empty router.
this.router.navigate(['/home'], { fragment: 'top' });
would work if 'home' is declared as a route and you have the id="top" element on it.
I know you would like it to be "pure Angular way", but this should work (at least):
gotoTop(){
location.hash = "#navbar";
}

How to scroll at top of the page in ionic

currently i am working in ionic framework on javascript and angular-js i just put the search box and render list of customer but suppose in first attempt i can search with 'a' it shows all item which having alpha 'a' but the problem is when i scroll down to see the search result list and at the bottom if i want to search with 'd' this time it gives result but at the top of the page but my scroll is at the bottom of the page.
So to solve the above problem i want set scroll position at the top of the page when search query is empty and display all customer so what should i do to solve this problem
thanks in adv..
You can try :
$ionicScrollDelegate.scrollTop();
http://ionicframework.com/docs/api/service/$ionicScrollDelegate/
For Ionic 2 and higher use the scrollToTop() method on the content class.
page.html
<ion-content>
Add your content here!
</ion-content>
page.ts
import { Component, ViewChild } from '#angular/core';
import { Content } from 'ionic-angular';
#Component({...})
export class MyPage{
#ViewChild(Content) content: Content;
scrollToTop() {
this.content.scrollToTop();
}
}
See http://ionicframework.com/docs/api/components/content/Content/#scrollToTop
I normally do this on my home page.
import { Component, ViewChild } from '#angular/core';
import { Content } from 'ionic-angular';
#Component({...})
export class MyPage{
#ViewChild(Content) content: Content;
scrollToTop() {
this.content.scrollToTop(400);
}
ionViewDidEnter(){
this.scrollToTop();
}
}
Or you can call scrollTop() whenever you want.
Note: 400 is duration in milliseconds, it is optional and you can use this as well
this.content.scrollToTop();
in this case scrollToTop() will set the default value of 300.
For Ionic 4 this has been renamed from Content to IonContent, along with a new package name:
Breaking: Component Imports Changes
Making the snippet look like this:
import { Component, ViewChild } from '#angular/core';
import { IonContent } from '#ionic/angular';
#Component({...})
export class MyPage{
#ViewChild(IonContent) content: IonContent;
scrollToTop() {
this.content.scrollToTop(400);
}
ionViewDidEnter(){
this.scrollToTop();
}
}
Thanks #Junaid (https://stackoverflow.com/a/48987846/156388) for the base of this answer.
I didn't edit that answer as it's still valid for Ionic 2-3.
The answer above will scroll all your views to top. If you want to have more control then you will have to use a delegate handler .
First whatever you want to scroll you will have to add the delegate handler name
<ion-content delegate-handle="dashboard">
......
</ion-content>
In your controller you will have to use this handler
$timeout(function(){$ionicScrollDelegate.$getByHandle('dashboard').scrollTop(false);});
I would recommend using a $timeout because if there is current digest cycle it will not work. Also change false to true if you want to animate the scroll. Lastly dont forget to inject $ionicScrollDelegate and $timeout in your controller
For Ionic 4.X Latest Stable Release Try this
Source Link
In Page add Angular variable id on ion-content tag
<ion-content
[scrollEvents]="true"
(ionScrollStart)="logScrollStart()"
(ionScroll)="logScrolling($event)"
(ionScrollEnd)="logScrollEnd()"
>
<ion-button (click)="ScrollToTop()">
Scroll To Top
</ion-button>
</ion-content>
In component add methods
logScrollStart(){
console.log("logScrollStart : When Scroll Starts");
}
logScrolling(){
console.log("logScrolling : When Scrolling");
}
logScrollEnd(){
console.log("logScrollEnd : When Scroll Ends");
}
ScrollToBottom(){
this.content.scrollToBottom(1500);
}
ScrollToTop(){
this.content.scrollToTop(1500);
}
ScrollToPoint(X,Y){
this.content.scrollToPoint(X,Y,1500);
}
For Ionic 4, the approaches here helped a lot. However, a second param was needed on
#ViewChild(IonContent) content: IonContent;
So, I set the static false, as suggested here. But it only worked for me when I changed:
#ViewChild(IonContent, {static: false}) content: IonContent;
to
#ViewChild(IonContent, undefined) content: IonContent;
In Ionic 6+ you need to declare the element's ID to refer to, you could use any when declaring the type, but to be specific you can set IonContent as per previous versions. This is obviously for the Angular flavour of Ionic.
So after you add the ID, for example I have called my content "content":
Now you can refer to this element in the TypeScript via ViewChild as per previous versions.
Now you can utilise the methods outlined in the docs. For example:

Categories

Resources