Angular 2 routes - redirect to different app - javascript

I'm generating various versions of my app in alternate languages. I'm using AOT (ahead of time) compilations, so I end up with static deployable sites in a structure that looks like this:
dist -
index.html -- entry file for the default (English language) app
-fr
index.html -- entry file for French language version
-de
index.html -- entry file for German language version
I can currently switch between the main language websites using a dropdown where the user can select their preferred language, and I then load the main entry file for the required site using plain JavaScript like this:
const baseUrl = window.location.origin;
window.location.href = baseUrl + '/' + requestedLanguage + '/index.html'; // e.g. requestedLanguage = 'fr'
This works, as it seems that requesting the actual index.html file means Angular won't interpret the request href as an Angular route.
What I want to happen though is that when the user enters a URL that already contains the language version in the path, I want that language version to be served. I also want the URL path preserved so that the Angular routing loads the appropriate component for the requested URL.
For example:
user enters myDomain.com/fr/myPage
the app under the /fr/ subdirectory is loaded, and the Angular routing in that app loads the related component for MyPage
Currently if I enter a URL myDomain.com/fr/myPage, the Angular routing tries to interpret the desired subfolder fr as a route, which doesn't exist, so I get the following error:
Error: Cannot match any routes. URL Segment: 'fr/instruments'
How can I load the required app and the correct component? There must be a way of getting Angular to recognise that the fr in the URL refers to a different app. Maybe I'm missing a build configuration or something? Here's my script in package.json for building the French language version:
"build:fr": "ng build --aot --output-path=dist/fr --base-href /fr/ --i18nFile=src/locale/messages.fr.xlf --i18nFormat=xlf --locale=fr",

just use Components instead of different separate apps and use below example
>
{path:'',component:EnHomeComponent},
{path:'contact',component:EnContactComponent},
{path:'fr',component:LayoutComponent,
children:[
{path:'',component:FrHomeComponent},
{path:'contact',component:FrContactComponent}]}
then you can directly access the pages by URL

Use angular router concept for different paths of English, France and Danish.
Then use the path based on language.

I was able to load differing language versions of the app by configuring the pipeline for my .NET back end like this, so that the Angular static index page is loaded for each different language app (referred to as 'SPA' in the code). It works by checking if there is an 'index.html' page for the first subfolder in the request URL (e.g. '/fr/', '/de/'), and it loads that page if it exists:
Startup.cs
public class Startup
{
public void Configuration()
{
app.Use((context, next) =>
{
if (!context.Request.Path.HasValue)
return next();
IFileInfo fi;
string spaIndex = "index.html";
Uri uri = new Uri(context.Request.Uri.ToString());
var segs = uri.Segments;
var folder = segs.Length > 1 ? String.Format("/{0}", segs[1]) : "/";
if (!physicalFileSystem.TryGetFileInfo(context.Request.Path.Value, out fi)) {
// check if this is a request for a sub-application, e.g an alternative language version
// if so, load the app
if (physicalFileSystem.TryGetFileInfo(String.Format("{0}{1}", folder, spaIndex), out fi))
{
context.Request.Path = new PathString(String.Format("{0}{1}", folder, spaIndex));
}
}
return next();
});
}
}
The remainder of the URL (the part after the language subfolder) is then interpreted as a route inside the app that has been loaded (e.g. the French language app). This means that the correct component is loaded for the app (I'm not entirely sure how this part is working - maybe the remainder of the path falls through to a different part of the .NET request pipeline and is passed onto the Angular app?)

Related

Display static HTML file for Vue.js root URL

I'm new to Vue and am trying to figure out the best way to do the below.
Let's use example.com as our domain name.
We have a Vue.js app deployed that allows our customers to create their own subdirectory in our Vue.js app (e.g., example.com/user1page and example.com/user2page). Right now example.com goes to a Vue.js login page
Marketing recently sent us a home page (built in pure HTML/CSS/JS) that they need to display at example.com. Is it possible for me to upload the HTML/CSS/JS for that page in a Vue static asset folder and render that for example.com; then render our actual Vue.js app for anything example.com/*?
Due to business reasons we cannot:
Change the vue.js app to a different domain or subdomain (because customers have already published pages)
Change the marketing homepage to a different domain / subdomain / subdirectory
As an aside, we're using Clouflare for our DNS. Unfortunately their page rules won't be able to solve this issue.
Any help would be greatly appreciated.
Thanks very much!
Ed
I would solve this with a webserver configuration if you have access to it.
In NGINX you can define different locations with different root-folders.
So if a user access to main page it would it the first route and serve the static page and if it would it the regex for the client page it would serve the vue application (you could also specify the vue server here)
location / {
root /var/www/static-html-folder;
}
location /paths-to-clientpages {
root /var/www/vuepage;
}
For the location paths you can use regex to match all routes
I figured out that the way to do this in Netlify is to add the following command to your toml file:
[[redirects]]
from = "/"
to = "your marketing page URL"
status = 200
force = true

Serving external resources in Angular 11

I am currently building a gallery app using Angular 11 + Electron + Java, but I came across this issue that I have not managed to solve.
Using the backend, I get all the files within a folder the user chooses, but then, when i use the paths as src for , Angular adds http://localhost:4200 before the path.
I can't use the asset folder because the source path of the folder containing the images is chosen by the user and may vary across different PCs.
What is the proper way to deal with this?
I have found a solution.
First thing is to set
webSecurity: false
in electron's main.ts file.
Then, in the same file, register the following protocol:
app.on('ready', () => {
setTimeout(createWindow, 400);
protocol.registerFileProtocol('file', (request, callback) => {
const pathname = decodeURIComponent(request.url.replace('file:///', ''));
callback(pathname);
});
});
Finally, when using the image path, add file:// before the absolute path of the image.
This carries potential security issues, so carefully evaluate how your app is going to be used!

How do I add another page in an angular-cli project?

Based on the comments on another of my questions (gradle how to add files javascript fies to a directory in the war file) I'm trying to use angular-cli to help build and manage an angular project. However, I cannot seem to find any documentation on how to create a second webpage in the project, which to me seems like a very basic task. I tried creating a "component" with ng g component {component name}, but this didn't add anything to the build result.
I had missed the section of the angular docs on routing since I did not make the connection between the word "routing" and what I wanted to do. Routing as described here works perfectly when using Node as your server. However, other web servers such as Tomcat (which I am using for this project) will not since ng build only generates an index.html file. Node knows that it should re-route URLs under the angular base to that file, but Tomcat doesn't. A proxy server such as apache needs to be placed in front of the Tomcat server to redirect the urls to the base url for the application.
With that out of the way, here is the basics of routing:
create a component for each "page" (the component does not need to be responsible for the whole page displayed. see 2)
create a "shell" component that contains features that will be on all pages e.g. toolbar, side navigation.
add <router-outlet></router-outlet> to the point in the shell component component where components for sub-URLs will appear (note that they are inserted into the DOM after this tag, not within it.)
in the imports for your module, add RouterModule.forRoot(). This function takes an array of Route. Each route has a path and a component property. path is the url (relative to the base url) that will cause component to be inserted into the DOM. Note that path values should not begin with a slash.
add a tags with the routerLink property bound to the url of your new page. Note that here, there should be a leading slash.

Handling Dynamic Routes Without a Server

Is it possible to serve a dynamic html page without a backend server or without using a front-end framework like Angular?
Edit
To clarify, the index file is served from a backend. This question is about how to handling routing between the index and dynamic pages.
I have an application that consists of two files - index.html and dynamic.html. When the user clicks an option say "Option A", they are served dynamic.html and the url is updated to /option-a. Now, with a server this is no problem and assuming the user visits the app from the landing page, it isn't a problem either because a cookie can be set. However, suppose a user visits a page at my-domain/option-a. That route doesn't exist and there is no server to redirect so it will 404. They would have to visit dynamic.html.
I think this architecture demands that there's either a server to handle route redirects or a SPA framework.
Is there something I'm missing?
your SPA framework will be active only once your HTML page is loaded and to do that you need to redirect any URL that user tries for your domain to that HTML file. For this you obviously need a server (and since you are talking about my-domain/option-a I assume you have atleast a basic server). You can refer to this link to get an idea on how server can redirect a URL to specific html file: Nodejs - Redirect url.
Once HTML is loaded you can initialize your SPA framework and decide the template to be loaded based on the URL.
Note: without a server you will access URLs using file://somepath/index.html and anything other than this URL will result in 404 and no SPA framework can handle that.
I think the solution is to use a static site generator such as Jekyll or Middleman and allows you to convert information into static pages. That way you functionally are building a bunch of pages but they are all compiled ahead of time. You can add dynamic content that is loaded in from a yaml file and it will compile the content into separate html pages.
It is not possible, but there is a workaround using url parameters like this:
my-folder/index.html
my-folder/index.html?=about
my-folder/index.html?=about/sublevel
my-folder/index.html?=profile
my-folder/index.html?=./games
const urlParams = new URLSearchParams(location.search);
const route = urlParams.get('');
console.log(route);
// Should print "about" "about/sublevel" "profile" "./games"
Of course this approach is not as clean as using a server for routing, but it's the best you can get without a server.
BTW. I tried an alternative solution creating symlinks with all the target routes pointing to the same index.htmlfile. But it did not work because the browser (firefox) redirects by default when it finds a symlink, thus home is shown all the time.

Deeplink to Ember app from outside

How can I deeplink to my Ember app from outside ?
Say I want to deeplink to within my ember route (mainPage\deepRoute)
So when user clicks on the external link (not part of my Ember app), he is directly taken to mainPage\deepRoute
How will I code such a link ?
I assume by default the Ember application template would be rendered, but I want to direct route to some other link/template ?
You can simply link inside to any route of your Ember.js app directly, however your webserver has to be configured with url redirect to the index.html.
For example, if you use nginx as a webserver, you should have something like this in your nginx config file:
location / {
try_files $uri /index.html;
}
Option Two: if you cannot update the webserver, for example, you use GitHub pages, you have to use the #-ed url option. In this case, a url looks like this: example.com/#/posts/1/comments
More info here: http://guides.emberjs.com/v2.1.0/configuring-ember/specifying-url-type/
Make sure the server will load the single Ember html page for that url. You can create a 'catchall' route in your web framework that aliases (not redirects to) your index.html view, - probably at the bottom of your server route definitions - or manually alias whichever specific route you are concerned with.
Then once Ember is loaded it will enter the route specified in the url and use any query params that were specified.

Categories

Resources