I am searching for the correct way to correct to scroll in a page that will load dynamic information. These informations are asynchronous so to avoid my user seeing the whole page constructing itself I have a boolean flag like so :
<div *ngIf="loaded"> ... </div>
My problem is that I want to scroll to an anchor using the angular router, but that anchor doesn't exist yet at this moment because the load isn't finished.
The anchor :
<hr id="my_anchor">
the code I use to load the page and get to that anchor :
<a [routerLink]="['/some/route/', idParameter]" fragment="my_anchor">...</a>
You probably want to use virtual scrolling, available through the Angular CDK:
https://material.angular.io/cdk/scrolling/examples
https://medium.com/codetobe/learn-how-to-us-virtual-scrolling-in-angular-7-51158dcacbd4
This approach dynamically loads only those components that are on screen, allowing you to load extremely large datasets.
It is also possible to code this manually using:
const el: any = document.elementFromPoint(x, y);
This Javascript function determines which HTMLElement is located at a specific x, y, coordinate and thereby determining which elements are on screen. Using this information you can wrap all items in a list like so:
<ng-container *ngFor="let data of datas">
<ng-container *ngIf="data.isOnScreen">
<app-my-component></app-my-component>
</ng-container>
<ng-container *ngIf="!data.isOnScreen">
<div class="empty-div"> </div>
</ng-container>
</ng-container>
and style the empty-div to be the same size as a non empty div. This ensures that scrolling works. I got this working well. However, no doubt the CDK makes this a whole world smoother and easier.
The only benefit with my custom approach is it gives you total control. You can easily use:
list.scrollTop = 999;
to scroll to any position in the list, thus supporting anchors (where list is the HTML list element that will scroll). Not for the feint hearted though, would only recommend this for confident coders.
i have an issue within my Angular7 application using the NguCarousel (uses HammerJS).
The carousel works as intended for displaying complex elements, until I add a html-select element in the carousel items.
Problem:
When clicking the select the whole carousel becomes draggable in Firefox.
This can be seen when editing this demo a bit.
In simple.component.html replace in row 3 {{item}} with <select></select>
Already tried the following things:
change framework: I have seen the same behaviour in swiper-framework (therefore probably not really framework related)
stop the event propagation with <select (click)="$event.stopPropagation()"> but that didn't help.
css touch-action: none one select
What else can i try?
Best regards
Terry
Edit: Still having this issue. A hint/idea would be splendid!
HammerJS uses pointerdown event to catch the start of dragging process.
So, that's probable what you wanted to stop from being propagated.
<select (pointerdown)="$event.stopPropagation()">
Forked Stackblitz
I am writing a suite of automated UI tests. I have a set of tests that verifies the links in a navbar work correctly, they take an annoying long time because it's loading 2 pages per test and there are many links in the nav bar. I am wondering if it is necessary to actually click the links?
One of the links would look like this, they're all basically the same, all contained inside a list of of <li> elements:
<a href="/projects/7d9162e5-e59c-452e-b9f5-684a2e0f2924/home" data-reactid=".0.2.0.0.0.$0.0">
<span class="icon icon-home" data-reactid=".0.2.0.0.0.$0.0.0"></span>
<span class="label" data-reactid=".0.2.0.0.0.$0.0.1">Home</span>
</a>
I could grab the content from the href attribute and request the page programmatically (don't load it in the browser) to assert that the href is correct and this would be significantly faster.
Is there any chance that an element could have an href attribute that points to the page as expected, but for whatever reason clicking on this element could be broken?
This might be the solution that you are looking for:
Link to Page
That code would append the href attribute as text to the body every time a link was clicked but not actually go to that link. The return false; part of that code prevents the browser from performing the default action for that link. That exact thing could be written like this:
$("a").click(function(e) {
$("body").append($(this).attr("href"));
e.preventDefault();
}
By taking the href content, you might risk that your automation passes test even though the navbar link does not work. It could be that navbar link was disabled by mistake, but as the link is still present in the DOM your automation will not capture it.
Just my 10 cents...
I'm using uib-pagination pretty much successfully, but the data I'm paging right now is massive and as it turns out the number of pages is very large, and so I'm having around 2800+ buttons at the end of my page. I need to somehow give the user the chance to navigate through pages using a smaller number of buttons.
Let's say I need buttons to be [1][2][3][4][5][6][7][8][9][10][Next 10 Pages]...[Previuos 10 Pages][2790][2791][2792][2793][2794][2795][2796][2797][2798][2799][2800]
This is the html
<uib-pagination total-items="SearchCriteria.PageInfo.Total_Items"
items-per-page="SearchCriteria.PageInfo.Pg_sz"
next-text="Next"
previous-text="Previous"
ng-model="SearchCriteria.PageInfo.Pg_no"
class="pagination-sm"
boundary-link-numbers="true"
ng-change="GetPaged()">
</uib-pagination>
and this is the component I'm using: ui-bootstrap-tpls-1.0.3.js
Is there any attribute I can use to achieve this?
Use max-size attribute
<uib-pagination
max-size= "maxSizeValue">
</uib-pagination>
I have an array of 2000 items, that I need to display in html - each of the items is placed into a div. Now each of the items can have 6 links to click on for further action. Here is how a single item currently looks:
<div class='b'>
<div class='r'>
<span id='l1' onclick='doSomething(itemId, linkId);'>1</span>
<span id='l2' onclick='doSomething(itemId, linkId);'>2</span>
<span id='l3' onclick='doSomething(itemId, linkId);'>3</span>
<span id='l4' onclick='doSomething(itemId, linkId);'>4</span>
<span id='l5' onclick='doSomething(itemId, linkId);'>5</span>
<span id='l6' onclick='doSomething(itemId, linkId);'>6</span>
</div>
<div class='c'>
some item text
</div>
</div>
Now the problem is with the performance. I am using innerHTML to set the items into a master div on the page. The more html my "single item" contains the longer the DOM takes to add it. I am now trying to reduce the HTML to make it small as possible. Is there a way to render the span's differently without me having to use a single span for each of them? Maybe using jQuery?
First thing you should be doing is attaching the onclick event to the DIV via jQuery or some other framework and let it bubble down so that you can use doSomething to cover all cases and depending on which element you clicked on, you could extract the item ID and link ID. Also do the spans really need IDs? I don't know based on your sample code. Also, maybe instead of loading the link and item IDs on page load, get them via AJAX on a as you need them basis.
My two cents while eating salad for lunch,
nickyt
Update off the top of my head for vikasde . Syntax of this might not be entirely correct. I'm on lunch break.
$(".b").bind( // the class of your div, use an ID , e.g. #someID if you have more than one element with class b
"click",
function(e) { // e is the event object
// do something with $(e.target), like check if it's one of your links and then do something with it.
}
);
If you set the InnerHtml property of a node, the DOM has to interpret your HTML text and convert it into nodes. Essentially, you're running a language interpreter here. More text, more processing time. I suspect (but am not sure) that it would be faster to create actual DOM element nodes, with all requisite nesting of contents, and hook those to the containing node. Your "InnerHTML" solution is doing the same thing under the covers but also the additional work of making sense of your text.
I also second the suggestion of someone else who said it might be more economical to build all this content on the server rather than in the client via JS.
Finally, I think you can eliminate much of the content of your spans. You don't need an ID, you don't need arguments in your onclick(). Call a JS function which will figure out which node it's called from, go up one node to find the containing div and perhaps loop down the contained nodes and/or look at the text to figure out which item within a div it should be responding to. You can make the onclick handler do a whole lot of work - this work only gets done once, at mouse click time, and will not be multiplied by 2000x something. It will not take a perceptible amount of user time.
John Resig wrote a blog on documentDragments http://ejohn.org/blog/dom-documentfragments/
My suggestion is to create a documentDragment for each row and append that to the DOM as you create it. A timeout wrapping each appendChild may help if there is any hanging from the browser
function addRow(row) {
var fragment = document.createDocumentFragment();
var div = document.createElement('div');
div.addAttribute('class', 'b');
fragment.appendChild(div);
div.innerHtml = "<div>what ever you want in each row</div>";
// setting a timeout of zero will allow the browser to intersperse the action of attaching to the dom with other things so that the delay isn't so noticable
window.setTimeout(function() {
document.body.appendChild(div);
}, 0);
};
hope that helps
One other problem is that there's too much stuff on the page for your browser to handle gracefully. I'm not sure if the page's design permits this, but how about putting those 2000 lines into a DIV with a fixed size and overflow: auto so the user gets a scrollable window in the page?
It's not what I'd prefer as a user, but if it fixes the cursor weirdness it might be an acceptable workaround.
Yet Another Solution
...to the "too much stuff on the page" problem:
(please let me know when you get sick and tired of these suggestions!)
If you have the option of using an embedded object, say a Java Applet (my personal preference but most people won't touch it) or JavaFX or Flash or Silverlight or...
then you could display all that funky data in that technology, embedded into your browser page. The contents of the page wouldn't be any of the browser's business and hence it wouldn't choke up on you.
Apart from the load time for Java or whatever, this could be transparent and invisible to the user, i.e. it's (almost) possible to do this so the text appears to be displayed on the page just as if it were directly in the HTML.