I'm using AngularJS not to build SPA but just for certain features in the system. I'm having a trouble to find out why Angular is preventing page from being refreshed after it get's there or how to disable/workaround it.
So I have simple menu:
<ul>
<li>Homepage</li>
<li>Profile</li>
</ul>
And when I'm already on the http://example.com/admin page and I'm clicking in first link (/admin) then nothing happens.
I could detect if a certain a element has a href and then use window.location but unfortunately I'm using AJAX in some other parts of the system so that won't fit.
Please advise.
You're working with a Single Page Application. The router takes care of navigating between different application routes, but the browser never fetches an entirely new page.
When you click on a link for a page that you're already on, there is no where to navigate to.
EDIT: You could write a directive that will detect clicks on anchor tags, and if the route is the same, it could trigger a page refresh. That will give you the behaviour you're looking for. However, I struggle to where this would be desirable.
EDIT 2: This is what stops your navigation: https://github.com/angular/angular.js/blob/v1.5.x/src/ng/location.js#L889.
As far as I can see, there is nothing you can do to disable that behaviour, or if there is, it will be an uglier and more fragile solution that creating your own directive that will trigger a page refresh.
you need to be using ng-href and http://plnkr.co/edit/stdkjN?p=preview
Related
I am working with a Dashboard that has a menu. Let's take the attached menu as an example (which is NOT mine, I took a snapshot from a video).
Could you give me an idea of how I can do so that when pressing an option from the side menu, the content on the right side changes. Should I create an html document for each possible option and reference it from an "a href tag" or is there some other way to do it? Preferably the solution or idea does not involve react, angular or vue.
If you are not using any of SPA (Single page Application) then you must have to go for multipage activities where you need href on each option given in your main menu.
Say there is piece of text (regardless of whether it is styled as a "traditional" link or button) on a page that when clicked leads to a new page with a new page/URL. But the navigation happens programmatically (e.g. via react-router using the History web API) instead of a hard HTTP refresh.
In this case, should it be a traditional anchor link with href attribute such as # or a button?
Option 1:
<a href="#" onClick={navigateToNextPage}>Link</a>
The downside is that you have a junk href attribute. You could remove that but then it is not in the tab order and doesn't get default link styling (though these could be overcome with one-off styling). Also if you copy the link it will copy as # which is incorrect and be interpreted incorrectly by screen readers.
Option 2:
<button onClick={navigateToNextPage}>Link</a>
The downside here is that if you want it to look like a traditional link you need to apply custom styling. Also in some ways it is really acting like a traditional link in my view. But this would be better for screen readers.
I can't comment on React but here is the correct method for SPAs, implementing it should be trivial in React.
Short Answer
Use a hyperlink (<a>) to navigate between pages and when loading additional content if no other option is available.
More simply: if the URL changes or you add large amounts of information to the page, use a hyperlink.
Long Answer
In your question you mentioned the History API and react-router.
For this reason I assume that the function navigateToNextPage changes the URL.
I also assume that I could access that page directly if I desired by entering that URL into my browser.
With those assumptions in mind you should use:-
<a href="new-page-url" onClick={navigateToNextPage}>Link</a>
Obviously you would stop the default action (e.preventDefault() or React equivalent).
A couple of points on why to use the format described above:-
Accessibility - when I encounter a hyperlink with a screen reader I am able to ask my screen reader where that link will take me, this is reassuring, I can't do the same with a button. This is why I didn't use # for the hyperlink but instead added the actual destination. If you see href="#" it is nearly always a sign that the wrong element is being used or it is being used incorrectly. After reading your comments about performing an action before navigating this is still perfectly valid, perform your action and then redirect, it is still navigation at the end of the day.
Accessibility - when I am navigating a site via a screen reader I may decide to cycle through all the hyperlinks on the page to get a feeling for the page structure. (NVDA modifier + K to get next link for example). I am very unlikely to loop through all the buttons on a page to look for navigation.
Accessibility - If I encounter a link I expect the page to change (even via AJAX). If I encounter a button I expect it to perform an action on the current page. Expected behaviour is a key part of accessibility.
Accessibility - hyperlinks have some important states. 'visited' is a key one on pages with lots of links as I may want to review something I read earlier and being able to navigate via visited links (e.g. NVDA modifier + K for all unvisited links). Buttons do not expose this information. An important point here is that you also can't style a button with button:visited in your CSS so you miss out on the visual clue for everybody there.
Accessibility - Space key vs the Enter key. If I land on a link I am expecting to press space to navigate, a <button> only works with the Enter key and so I may be confused as to why the page isn't changing. (I am assuming at this point you have used a load of aria to convince me this button is a hyperlink).
Robustness - If your site has limited functionality when JavaScript fails a hyperlink is far better than a button. It will still work when JavaScript fails and this is especially useful when a JavaScript failure may only be a temporary load problem with one page, allowing a user to get to another functioning page.
SEO - I dare to speak of SEO on Stack Overflow? Shame! Shame! Shame! :-P - but seriously although Google is pretty darned smart in what it can do on JS powered sites it does still struggle to work out where a JavaScript only link will take it. If SEO matters for you then use a hyperlink with a valid destination so Google can map information correctly.
Probably other reasons I have forgotten to mention but I think I have made the point.
What do you have to consider when using AJAX to navigate between pages?
Although not part of your question I thought I would quickly add a couple of points for completeness.
You need to signal to a user that a page is loading if you are using a SPA pattern (and therefore interrupting normal navigation). e.g. I click your link you need to let me know that an action is being performed (loading.....) as you intercept the normal browser behaviour with e.preventDefault() or equivalent.
The simplest way is to use aria-live=assertive on a region that explains the page is loading. You can Google how to implement that correctly.
Additionally when the new page loads you need to manage focus.
The best way to do this is to add a level 1 heading (<h1>) to each page that has tabindex="-1".
Once the page loads the last action you perform in your JavaScript navigation function is to place the focus onto this heading.
This has two benefits:
it lets the user know where they are now
it also lets them know when the page load is complete (as AJAX navigation doesn't announce when the page is loaded in most screen readers).
By using tabindex="-1" it means that the heading won't be focusable by anything other than your JavaScript so won't interfere with the normal document flow.
You can just do e.preventDefault() when clicked on <NavLink> do your thing. Then navigate. NavLink generates <a> tag in HTML and provide active class by default when route is active. This allow you to style active state link.
import React from "react";
import { NavLink, withRouter } from "react-router-dom";
function Header(props) {
const handleClick = e => {
e.preventDefault();
console.log("DO SOMETHING");
props.history.push(e.target.pathname);
};
return (
<ul>
<li>
<NavLink exact to="/" onClick={handleClick}>
Home
</NavLink>
</li>
<li>
<NavLink to="/about" onClick={handleClick}>
About
</NavLink>
</li>
<li>
<NavLink to="/topics" onClick={handleClick}>
NavLink
</NavLink>
</li>
</ul>
);
}
export const HeaderNav = withRouter(Header);
Wokring example: https://codesandbox.io/s/react-router-5-rqzqq
I would recommend you to use semantic HTML. This means using the correct HTML elements for their intended purpose as much as possible.
Easier to develop with — you can get some functionality for free, plus it is arguably easier to understand.
Better on mobile — semantic HTML is arguably lighter in file size than non-semantic spaghetti code, and easier to make responsive.
Good for SEO — search engines give more importance to keywords inside headings, links, etc., than keywords included in non-semantic
s, etc., so your documents will be more findable by customers.
There's more details
SETTING
I have a webpage with index.html which includes lots of scripts.
If a user clicks:
<button ui-sref="SCMCompanyWizard()">
<span>Add New Company</span>
</button>
Then I send the user to a new view.
Problem Scenario 1
At this view, I have a button that will not work because the associated jquery did not load. I get this error:
TypeError: Cannot read property 'show' of undefined
But, if the user refreshes the page it will work.
Problem Scenario 2
So, I added a script into the secondary included view at the top of the html. I added a <script>...</script> include. Now both of the index.html and the secondary html page have the script include.
This will make it work if the user goes to the page, but the button will fail if the user reloads the page.
Question
How do I make a webpage that works in both scenarios?
Note:
This question has been asked in many different contexts, such as :Why do I have to refresh my page for a javascript function to work?
But the answer data-ajax="false" doesn't work in the context of angular
UPDATE 1
Adding a ui-sref-opts="{reload: true, notify: true}" to my ui-sref button did not work.
i don't know why, this is because I thought it forces a reload right when the user clicks the link.
I paired this button option with only having the on the index page.
a. (If is not currenlty like that) put the js/jq code inside the load function to ensure the whole page was been load before call any code
$(function() {
})
b. (plan b) Move the code to the bottom of the html, to ensure -again- the page is currenlty loaded before the code is called.
c. If your code is dynamically created, be sure to "activate" it after the dynamic DOM is rendered. (invoke the "on" events after the code is rendered)
HIH,
I'm developing an hybrid mobile app using a SPA with angularjs, so I'm using routes to determine which page will be displayed and I'm using transitions (angular style, with ng-enter, ng-leave, etc) to change between pages.
However I'm having problem when users try to go back in the application. First of all, I can't use window.history.back because not always the last page seen is the page that the back button must lead on, so I have to change the route to the correct location.
Anyone is willing to wait a bit when clicking in a item that will lead to another page, but the opposite is not real. When users tap the back button and the app change the route, it takes some time to render the page as if it were a new page, but users keep tapping the back button because they feel like the app has stopped working.
I wanna know if there is a way to keep in memory the elements of the page that were already rendered to fasten the process of going back on the application.
P.S.: I know this way I will need a good memory consumption tracking to prevent memory leaks and a expensive usage that would make the application even slower.
I guess ui.router with nested views should help you.
Please see example http://angular-ui.github.io/ui-router/sample/#/contacts/42/item/b
(link blog & fax)
As you see, click on the links don't lead to reload all page (only required content) but urls are different for each views.
There's documentation for nested views
https://github.com/angular-ui/ui-router/wiki/Nested-States-%26-Nested-Views
I have a link which has two actions. When I click on it, it opens a modal box via "ng-click", but it also transitions state via its "ng-href".
The modal box opening is intended. The state transition is not. However I need the URL in that state transition to persist.
When I try to use $locationChangeStart to prevent the state change, it also prevents the URL from changing. This is not preferable. I've also researched a bit, and found potential solutions in "reloadOnSearch". However it doesn't possible to point to a particular link. Not all of the links on the page do this, the other links are all normal links. Furthermore I don't know how to use reloadOnSearch with ui-router.
The feature I'm trying to implement is similar to Pinterest's overlay of items. When you click on the item, they open up a modal box and change the URL, but the underlying page doesn't change. This allows the end user to copy the URL and share it with their friends, and when they access it, it will actually go directly the item page and not the overlay.
I'm currently using ui-router if that makes anything easier.
Hopefully somebody has a solution?
You can try angular ui bootstrap modal for better integration with angularJS.
Take a look at an example in http://angular-ui.github.io/bootstrap/
Or you may open a modal via data-target="#abc" instead of href="#abc"