First, let me say you will not be able to reproduce my problem unless you also are working in a healthcare situation using the latest athenaPractice EMR.
I just don't have any direction on where to troubleshoot this problem and looking for suggestions for what information or settings I should be checking.
I have an AngularJS SPA set up that routes 100% fine in a regular Chrome browser window locally served (http-server installed via npm). I can load the main app page by URL (localhost:port/app, which redirects to /app/#!) and I can load the subpage by URL (localhost:port/app/#!/page). I can do it with or without a trailing /. I can navigate from one view to the other by links on the page. Works great.
But I have a problem when I put it in the server location (which, if it's relevant, has a path longer than /app/ from the //localserver/ root), and load the file through the EMR (which is running Chromium). (Files are loaded in the EMR by adding a specially formatted file that links all included items in a form, which in the case of HTML files, is just a URL to a resource: //localserver/directory/subdirectory/app/#!/page). It loads fine the first time, but if I try to load separately a different page (//localserver/directory/subdirectory/app/#!/, for example), it shows the currently open page. It's almost like both instances of the browser are the same browser window and it doesn't bother to load a new window for the URL with the same address up to the #!. I can navigate from one page to another by links but not by loading from the root address, and if I navigate under one "form", and click back to the other one, it's also been navigated, hence why I think it's only one instance of the window.
I tried HTML5 routing with no success since this is running in a JBoss 7.x server and I have had a very hard time finding any documentation that even comes close to matching the files I see on the server for URL rewriting access. (I have found instructions that reference files that don't exist in our installation, so I don't know if this has been customized by the application provider, or what.)
I don't have access to developer tools, console, or even the address bar through the EMR.
Any suggestions on where to go with troubleshooting this?
Edit to add: Might be worth noting that I have tried ngRoute and ui-router both with the same results.
I got this working correctly. I don't know what the root cause in the EMR is, but it was treating each loaded route of the SPA as part of the same instance using #! routes. Getting HTML5 routing working solved the issue.
After fighting with Undertow for a day and having no feedback on why my rules weren't working, I ended up using Tuckey's URL Rewrite. It helpfully logs what input it was comparing against what which allowed me to see where my first attempts at rules went wrong, and edit them accordingly until they worked.
This required three file changes in the WEB-INF directory inside the application's .war directory. (There are various META-INF and WEB-INF directories all over in this setup but using this one worked in the specific deployment I'm working in now, namely our demo server.)
Create a /lib directory inside WEB-INF and put urlrewritefilter-4.0.4.jar in it (downloaded from the Maven repository)
Put the example urlrewrite.xml into WEB-INF and adapt it with necessary rules. For the root page of our SPA and the first route, the custom rules I inserted look something like this:
<rule match-type="regex" enabled="true">
<condition type="request-filename" operator="notfile" />
<condition type="request-uri" operator="notequal">(\.html|\.js|\.css)</condition>
<from>^/FormsFolder/subfolder/app/$</from>
<to last="true">/FormsFolder/subfolder/app/index.html</to>
</rule>
<rule match-type="regex" enabled="true">
<condition type="request-filename" operator="notfile" />
<condition type="request-uri" operator="notequal">(\.html|\.js|\.css)</condition>
<from>^/FormsFolder/subfolder/app/route1/$</from>
<to last="true">/FormsFolder/subfolder/app/index.html</to>
</rule>
Add the Tuckey Rewrite Filter to web.xml:
<filter>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
<init-param>
<param-name>confPath</param-name>
<param-value>/WEB-INF/urlrewrite.xml</param-value>
</init-param>
<init-param>
<!-- This configures how often to check for an update to urlrewrite.xml -->
<param-name>confReloadCheckInterval</param-name>
<param-value>60</param-value>
</init-param>
<init-param>
<!-- This configures what detail level of messages to log. TRACE was useful to
figure things out but DEBUG or WARN is probably more appropriate for production -->
<param-name>logLevel</param-name>
<param-value>TRACE</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
Lastly I had to update the index.html of the SPA to include the base tag, before all the stylesheet links and javascript script includes so that they route correctly. For the demo server, mine looks something like <base href="/demo/ws/FormsFolder/subfolder/app/"> but will have to be updated to publish to the live server.
Hopefully this is helpful if anyone else is trying to configure HTML5 routing on a similar JBoss server.
Related
In a Nuxt ("spa" mode) project I have a url with a dynamic param /shop/:product, which can be as such:
/shop/ipad-128gb-rose-gold
/shop/subway-gift-card
/shop/any-string
etc.
Using this directory structure works fine in development environment:
pages/
shop/
_product.vue
However it does not work in production. Looking to the generated bin/ folder I see that there is nothing inside shop/ directory. And I see that Nuxt mentions a solution here: https://nuxtjs.org/api/configuration-generate/#routes
But in my situation, I don't know what the :product param will be (could be any string).
I am fetching the product details in pages/shop/_product.vue from the server (if it exists), otherwise handling the error. So now how do I do that in a production build?
I think I am misunderstanding the Nuxt solution -- am I really supposed to generate all possible routes for every existing product slug??
The solution for me was to use:
// nuxt.config.js
export default {
...
generate: {
fallback: true
}
}
I am serving the app out of the built dist/ folder. And I came across this in the Netlify deployment docs:
For a single page app there is a problem with refresh as by default on
netlify the site redirects to "404 not found". For any pages that
are not generated they will fallback to SPA mode and then if you
refresh or share that link you will get Netlify's 404 page. This is
because the pages that are not generated don't actually exist as they
are actually a single page application so if you refesh this page you
will get a 404 because the url for that page doesn't actually exist.
By redirecting to the 404.html Nuxt will reload your page correctly in
SPA fallback.
The easiest way to fix this is by adding a generate property in your
nuxt.config and setting fallback: true. Then it will fallback to the
generated 404.html when in SPA mode instead of Netlify's 404 page.
References:
https://nuxtjs.org/faq/netlify-deployment/
https://nuxtjs.org/api/configuration-generate/#fallback
When you generate static pages, it produces directories and index.html in each one. How did you expect to have it dynamic if you serve static HTML?
You have 2 solutions:
don't use npm run generate. Run nuxt on the server. Using this solution, you avoid ajax in browser. Instead, nuxt performs it and sends the HTML to the browser. Good for SEO.
have your web server (nginx) point all requests to /index.html - at that point, javascript takes over and it can correctly find the slug and query the products via ajax. Bad for SEO because you need to use ajax to get the content after page finishes loading.
Documentation and configuration about this can be found at nuxt's web.
I have the following solution structure.
cabinet (folder)
cabinet.aspx
images (folder)
script (folder)
folder1
menu.js
userControl (folder)
menu.ascx
default.aspx
Inside of userControl I have menu.ascx (UserControl).
Inside of menu.ascx I am referencing several .js files. For example:
<script src="./script/folder1/menu.js"></script>
When I view the default.aspx that calls menu.ascx it works fine.
However, when I'm in the cabinet folder looking at cabinet.aspx (cabinet\cabinet.aspx) that also calls menu.ascx
<%# Register Src="../userControl/menu.ascx" TagName="menu" TagPrefix="uc2" %>
The menu code is in the source but the menu.js file is a 404
http://localhost/cabinet/script/menu-files/menu.js
It looks like it needs to go directory further out. I would of expected it to go to:
http://localhost/script/menu/menu.js
What do I need to do to accomplish this?
One of two approaches:
Anchor the script reference to the site root with an absolute reference via "/script/folder1/menu.js" (note how it starts with a forward slash). For example, <script src="/script/folder1/menu.js"></script>. This says to look at the root of the site and carry on from there.
Have the script tag runat="server" and root it to the application root via "~/script/folder1/menu.js" (note the "~/" start). For example <script runat="server" src="~/script/folder1/menu.js"></script>. This determines the site root server-side and generates the correct path accordingly.
In all cases except for when your development environment doesn't allow it (I'm showing my age there going back to WinXP for development) or you are configuring an app that will live in a virtual application sub-directory in your site, go with the first option.
I figured out that the issue was the Visual Studio Web Instance that was being fired off and the fact that there were headers that needed to be set on IIS to allow the code to work.
So essentially I installed IIS 7.5 and created a site and now I just attach to the process to do my debugging for this.
Once I got IIS setup correctly the paths that were in code worked.
I have been researching over this for some time now, have come across quiet a few stackoverflow discussions which are similar but none of which answer this question to my satisfaction. I am not sure if angularjs has a way to do this, but I am sure there is a way to do this when writing angularjs SPA applicaiton. Here goes my situation,
I am writing an AngularJs front end for an existing ASP.NET MVC based application.
The URL in the current application look like
https://domain.com/login
https://domain.com/profile
https://domain.com/settings
etc
My new frontend version reads
https://domain.com/index.html/login
https://domain.com/index.html/profile
https://domain.com/index.html/settings
Problem I need with is,
I need to remove the .html from the new urls. This is my first hurdle. Everything that I need to do later depends on how my URL reads. It needs to read in a format ASP.NET MVC provided. A url without the .html file extension in the URL.
When I googled for suggestions with keywords "angularjs url remove html and #!"
The top two results I get are
How to remove index.html from url on website based on angularjs
and
Removing the fragment identifier from AngularJS urls (# symbol)
none of which are quiet helpful in solving my situation.
There is a workaround I am considering if there is no better way to do this, which would be
"Since Index.html is where my ng-view resides and essentially this page drives my SPA architecture, so I can do into my IIS and set Index.html as a default document" What this does is helps me achieve what I want (not show ".html" in the URL) to a certain extent. For example (when working locally) if I navigate to http://localhost it will open the index.html without the file name being displayed in the URL and the angularJs routing still works fine as long as I don't refresh or copy paste those URLs (without index.html in them) in which case I get 404 errors (when I use $locationProvider.html5Mode(true) to remove the #s).
This surely is not the ideal solution because when the system emails users with URLs they need to use to access certain parts of applicaiton, we will invariably need to include the index.html in there (which we do not want to)
Any help, extremely appreciated. Thanks.
It's server side problem, not cliend side. You must handle request from server side like this:
handle '/'
return view 'index.html'
Then when you visit https://domain.com/, you will see index.html file, but it will not be visible in url.
EDIT
If you are using angular's html5 mode then you shall do more complex routing, something like this:
handle '/'
handle '/login'
handle '/profile'
handle '/settings'
return view 'index.html'
Because for example you are on url: https://domain.com/profile and you refreshed the page, request will be sent to this url, so you shall also handle '/profile' route and return same index.html page (then angularjs will take care about routing)
If you are using hash(#) then when you refresh https://domain.com/#/profile page, request will be sent to https://domain.com/ and '/' route handler will be enough
You can write a URL Rewrite rule in your web.config :
<rewrite>
<rules>
<rule name="Registration" stopProcessing="true">
<match url="^Registration"/>
<action type="Rewrite" url="/registration.html"/>
</rule>
</rules>
</rewrite>
This is my first time creating a mobile site for someone I have the javascript code all set up and when tested on my phone, it redirects it to: m.websitename.com, like I want it to. However, I have no idea what to name the file I am wanting it to redirect to? I saved the file under: mobile.html, but it isn't redirecting to it.
I don't want it to redirect saying www.websitename.com/mobile, I don't think it looks as professional.
Thanks
index.html or default.html is the convention. so why not direct to
m.websitename.com/index.html
and configure the subdomain so that m.websitename.com is actually pointing to websitename.com/m folder. so that folder can have its own index file.
You would probably want to do this using subdomain and destination setup from your server you are using (Most of webhosting companies made this easy through their software e.g. cPanel). Directory structures is going to look like this. So when user was redirected t m.yourweb.com/ then it's not going to have m.yourweb.com/mobie.
domain [directory]
css [directory]
js [directory]
index.jsp [file]
purchase.jsp [file]
...
subdomain [directory] <- for mobile
css [directory]
js [directory]
index.jsp [file]
purchase.jsp [file]
So when mobile user was detected, JS is going to redirect this user to the subdomain (for mobile) instead of normal directory.
The other recommendation (which is better I think) is use the same logic from the above but when user was redirected to m.yourweb.com/ load css file for mobile version web instead of normal web. loading css through JS
If you think this is complicated, you might be interested in having a look at CSS3 media queries. This basically changes CSS layout depending on current users' screen. resolution Media queries tutorial
You can have any filename you like. But as btevfik mentioned either put index.html or default.html
I recommend index.html
Also you can set the default file in you server configuration. By default most servers have the default file handler as index.html. For Apache it will be either index.html or index.php. You can change this to something like mobile-handler.html by changing the server configuration.
So whenever you access your site by http://your-site.com or m.your-site.com the default file specified in the server configuration is loaded.
Please note that your-site.com and m.your-site.com will have different site root, hence request will be handled by difffernt files.
I am not able to include http://maps.googleapis.com/maps/api/js?sensor=false. Whenever I load my portlet for the first time it doesn't work but if I refresh the same page then it starts working fine. I don't know what the issue is. Please Help.
One of the clean ways to include js file in a portlet, independent of the portal server is to configure in portlet deployment descriptor file as below. For liferay, it would be liferay-portlet.xml.
<portlet>
<portlet-name>MySamplePortlet</portlet-name>
<header-portlet-javascript>http://maps.googleapis.com/maps/api/js?sensor=false</header-portlet-javascript>
</portlet>