After removing the # from url, I lost direct access to my urls - angularjs

in order to make nice urls, I decide to remove the # from my ulrs using the tip from the following question Removing the fragment identifier from AngularJS urls (# symbol) Now, I realized that my urls are not working if I try a direct access to them. from the given example in the related question if put the url below directly in the browser http://localhost/phones
I'll get a 404.
Any idea how to solve this?

You need to write server side code that will generate the page that you were previously depending on the client-side JavaScript to generate.
This will then be the initial view for that URL.
If the client supports JavaScript (and the JavaScript doesn't fail for any reason) it will then take over for future interactions.
Otherwise, the regular links and forms you (should) have in the page will function as normal without JS.

Related

SSR and localization

I ran into a problem that I have never faced before developing a PWA with translations.
I state that I have always and only developed multilingual applications in Vue, React, Angular, and at the moment I am using Svelte.
I have always used simple practices, translation with a json dictionary and sending the Lang variable to the server for data acquisition in the requested language (set in the Headers).
All of this was fine until I encountered the need to receive the translated meta tags for the requested content immediately, during SSR, upon landing on the page. But as you know, at this stage there is no access to localStorage or similar, which is why it is impossible for me to acquire the meta tags in the requested language, since I do not have access to the variable set in the browser. How do you act in this case? I'm not interested in finding a specific solution for a certain framework, but a possible technique.
For Svelte I found this half solution, which allows me to obtain the slug / lang / from the address and use it in the server during the rendering phase, in order to obtain the data already translated on the server side.
Can I consider this a good solution?
I don't know what are you returning from the API, but if you have localized user defined content on backend, then this solution is good. If you are translating the app itself, you maybe you can give Tolgee a try, which supports SSR. https://tolgee.io/integrations/svelte

Dealing with %23 replacing id # in angular routing.

The problem:
I have a express backend/angularjs frontend web app hosting all of my teams documentation for our users. We frequently need to post links to a specific question (all linked as ids) to our users in Slack. ex. helpapp.com/productTheyNeedHelpWith#QuestionLinkedTo the problem is that when the link is clicked from slack, not when copy/pasted, Slack launches a new browser window/tab to helpapp.com/productTheyNeedHelpWith%23QuestionLinkedTo.
This breaks ngRoute as it no longer recognizes /productTheyNeedHelpWith as the path to load the correct page for and the user gets sent to our home page instead.
Thoughts on possible solutions:
I'd like to solve this issue either in the ngRouting itself by somehow updating the path by replacing %23 with # before $routeProvider does it's magic, or by somehow capturing the full url in app.js and updating it or redirect to an updated version before we've rendered a page view at all.
currently I've set a workaround by using a ng-init event to check the url and, if %23 is found, update it and replace it with the correct extension but this causes an odd double load that leads to a poor user experience.
Final Thoughts:
As I'm not sure of the best way to go about this, and because our code is proprietary, I'm avoiding posting to much 'example code' that may not be relevant but am happy to provide any parts of it that you, wonderful stackoverflowers, may request. Thank you in advance for your assistance.

URL handling in a Hypermedia (HATEOAS) driven AngularJS application

We are looking for some advice on handling URLs (and the state related to each URL) in a web application backed by a HATEOAS REST API, more specifically on
how to avoid having the web application URLs coupled with the REST API URLs
how to handle multiple resources in a single view
But let me first provide some more context:
We are building an Angular web application on top of a REST layer with Hypermedia constraint. (Note: I prefer simply using the term 'Hypermedia (constraint)' over HATEOAS).
As dictated by the Hypermedia constraint, the available actions and links in the application at any point in time are provided by the REST API. So the web application should not contain any hardcoded urls of the REST API, except for the 'root' (assuming that concept really exists in a REST API).
On the other hand, each page in the web application needs to be bookmarkable. So we cannot create a black-box application (with a single url and all state changes handled in the SPA without changing the URL). This means the web application also has its URL space, which needs somehow to be mapped to the REST API URL space. Which is already a conflict with the Hypermedia idea.
In the Angular application we use UI Router for handling application state. Here is how we got it working:
We only define states, no URLS
We defined a $urlRouterProvider.otherwise handler that will map the current web application URL to the corrsponding REST API URL, retrieve the representation of the resource that corresponds with that REST URL and pass it to the controller (in $stateParams).
The controller can then use the data (and links and actions) in the representation, just like it would if it would have made the REST call itself (or through a service)
So far so good (or not really) because there are some downsides on this approach:
The Web application URLs are mapped to the REST API URLs, so both URL spaces are coupled, which conflicts with one of the basic assumptions of using Hypermedia constraint: we cannot change the REST API URLs without having to change the web application.
In the $urlRouterProvider.otherwise handler we retrieve the representation of the current web app URL. But in some cases we have two resources in a single view (using UI Router nested states): for example a list of items and a detail of a single item. But there is only a single URL, so only the representation of the item detail is retrieved and the list of items remains empty.
So we would love to hear some suggestions on how we could improve on our approach in handling the two URL spaces. Is there a better way to make the REST API dictate the (available) behaviour of the web application and still have bookmarkable URLs in the webapplication? Because now we have some kind of hybrid approach that does not feel completely right.
Thanks in advance.
Regards,
Luc
that's a tough setup. Roughly you want bookmarks into your API, and RESTful systems somewhat discourage bookmarks.
One possible solution is a "bookmark service" that returns bookmark (bit.ly like) urls for the current resource being presents that are guaranteed to be fowards compatible because as you may change the canonical url structure, the bookmark service can always translate the bit.ly like url into the canonical url. Sounds complicated, but we see this all the time and we call them SEO urls eg: /product-name/ maps to products/ today, but may be /catalog/old-products/ tomorrow.
How you match that up to a UI that shows 2 resources the first being a list of summary like resources, and the second being a specific resource get's really tricky. I would expect such a page to know contain the state of what's it's displaying in it's url (probably in the fragment). As such since it's [likely] the controller that processing such commands it probably needs both (the list resource and the expanded resource) as input. I bet the url would look something like:
list=http://path/to/list/results&expand=http://self/link/of/path
So the last part you have is to make sure that works going forwards. Again this is the bookmark problem. What i may suggest if you don't want to build a bookmark service is that given you want to have such bookmarks you need to transition people to the new URLs. When a request is made to http://path/to/list/results and you want to switch that over you should be 301 redirecting them to the new canonical url and the app should be updating the bookmark. such a redirect can include the &flag=deprecate_message param to trigger the presentation in the UI that the client's bookmark is old and should be replaced. Alternatively the response can be internally forwarded and the deprecation flag & canonical (or latest) link included in the response to the old URL. This causes a phased transition.
In summary: I have yet to see HATEOAS be a cure all for backwards & forwards compatibility, but it's much better than the existing techniques. that said you must still make decisions in v1 of your API about how you want your users to move to v2.

Why should I put '#' before the path when routing with AngularJS?

When routing in Angular views we add the following. I don't understand the need to add #; if I remove it, I get a 404 Error.
a href="#/AddNewOrder"
Putting # in URL indicates start of the hash part, which is used to address elements inside a single page. In modern single-page web applications, this can be used to address application states.
If you don't put the # there, you're changing the path, which means you're creating a new URL and prompting the browser to load the content at that new URL instead of the current page.
As other posters have suggested, you don't have to use hashes when using html5mode. I left it out, because it brings a few challenges of its own, which I feel to be outside the scope of the question.
enter link description hereYou don't have to. You can configure your URLs to look like normal URLs, but in reality they will still work the same way.
Check https://docs.angularjs.org/guide/$location
And refer to html5mode
It will only work in modern browsers though. Old browsers will still show the hash. But the cool thing is that you can write your URLs the old/normal way.
# or fragment identifier is a way to indicate a specific portion of a single document. Without the #, the url corresponds to a different page.
For example www.yoursite.com/page links to the /page location of your website, while www.yoursite.com/#/location points to the same index page of your website but at a specfic point in the web page #location, or in your case, a different template view.
Angular routing can not load different templates for different server urls. It is specifically designed for single-page applications and any loading of partial views or templates has to happen on the same web-page or location. Hence only the fragment part of the url changes when using angularjs routing.
More information about fragments can be found here: http://en.wikipedia.org/wiki/Fragment_identifier

Deeplinking backbonejs with pushstate

Not sure what i am missing, but I have pushState working on my Backbone based app, where I could click around and have my URL look like www.example.com/route_specified, however if i try to go directly to that page it shows up as not found. If I do www.example.com/#route_specified it works, and quickly changes back to www.example.com/route_specified on the address bar
I am guessing i need to do something in Apache to handle this and make sure that all calls resolve to the index or something like that, but can't find explanation.
Correct. Think about it this way without pushstate enabled. Your server is still trying to serve the page at that route. Since it cannot find the specified document at that location, it throws a 404.
Technically speaking, your server should still produce some sort of result at the url location, then have Backbone take over. In it's simplest form, this is called progressive enhancement. The server should still serve some sort of static page with critical info, which will eliminate issues you will have with SEO. Work your site/app with javascript disabled, serving only the relevant data. Then have Backbone takeover. I have just come across Mashable's redesign, and they integrate progressive enhancement extremely well with Backbone.
If SEO is not a concern, you could always redirect the user to the index page. Just remember that search engines will only index your app page then. If your content is being served dynamically, there wont be any data to index.
Hope this helps.
Thanks
Tyrone

Resources