I'm writing a javascript app which is called within another page I do not control. I'd like to be able to embed an Angular JS app, but how do I handle routing without modifying the URL? How would testing (ie. e2e) work in this scenario?
Edit: The app is a wordpress plugin which is overlayed on the Wordpress dashboard, therefore the URL and Page History cannot be modified. The app will be bound to a div which is embedded in the page, and overlayed on existing content using CSS.
I believe you can just inquire AngularJS and your app, and using hooks to provide necessary HTML. A few things to note though:
Because the URL cannot be changed, you should use router in legacy mode (using URL hash) instead of HTML5 mode.
Since you're running in generated URL, the templateURLs must be built dynamically.
For example, ouput a script tag for URL to your plugin folder:
<script>var MY_PLUGIN_BASE = '<?php echo plugins_url(); ?>'</script>
And then later define your route and templateURL using that constant:
$routeProvider
.when('/', {
templateUrl: MY_PLUGIN_BASE+'my-plugin/views/main.html',
controller: 'Main'
})
This works, but in general I will avoid using routes in such situations. This cause more work in the controllers and directives, but it is safer because there could be other client side MVC apps on the page.
The ng-app is attached to the root element of your view instead of body.
For more general embedded AngularJS app (in my experience: a bookmarklet), you need to:
Inject AngularJS if needed (check for window.angular), CSS and HTML.
Inject your app's JS file. Because only one ng-app will be auto bootstraped, bootstrap your app manually using angular.bootstrap
angular.bootstrap(document.getElementById('my-app'), ['MyApp'])
Use absolute URL for templateURL, and make sure that URL have CORS enabled.
Again, avoid using routes if possible. For the Wordpress plugin, we're pretty sure that there's no other app using hash for routing (Wordpress is using Backbone, but I don't see the routes), but in general there are already a MVC app on the page that handle routing.
Related
I'm new to angular 2. Learned to develop single page application for website(front end). But what I want is after login, have to use another style sheet and js files dont load website's css, js files.
For example:
Before login
abc.com or abc.com/* => load css1, js1 files only(frontend site)
After login the page should change like Admin Template
abc.com/dashboard or abc.com/* => load css2, js2 files only(backend site)
May user can access frontend site even after they logged in.
Please help me how to do this.
The sample code I tried only for single page application from tutorial, so i think no need to post here. Let me know if my question not clear.
Note: it is in Angular 2 not Angularjs
You can do this by writing code in component CSS files and include that by using styleUrls. For dashboard write your CSS files inside that component.
For JS file you can load that particular js file by HTTP request before dashboard display.
I am working on an angular js 1.x application by using ui-router and have come up with a bottleneck since I am new to angular js ,so please forgive me if I sound silly.
Problem:
I have a main angular js app which has its own css files and script files(controllers,directives 3rd party libraries like bootstrap,angular etc and services files).
Now I have a landing page which has its separate design(it has its own css,scripts and images files).
Now I want to integrate the above mentioned landing page with its own separate files on the root route of the angular js app.
So my question is how should I do that ? , so that the css and scripts files don't conflict with each when I try to visit landing page and the route for the main application back forth.
I have tried oclazyloading the required files for landing page state and the main apps files respectively but they seem to conflict with each other's files.Since from what I think is happening is that the files that are already lazily loaded for the landing page conflicts with the files lazily loaded for the main app when I click on the main app link on the landing page.
Edit 1:
I also tried using angular-ui-router-styles it does the job since it unloads all the lazily loaded files before adding new files but what happens is that on page reload unstyled page occurs and then after few seconds it gets style because the package loads the css files after appending it in head tag
Suppose you have index.html in which you have to insert one page then your body section should be like this
<body>
<div>
<ui-view></ui-view>
</div>
</body>.
Now in your controller file suppose index.js your code should be like this
var myApp=angular.module("myModule",["ui.router"])
.config(function($stateProvider,$urlRouterProvider){
$urlRouterProvider.otherwise("/home");
$stateProvider
.state("homePage",{
url:"/home",
templateUrl:"site/homepage.html",
controller:"homePageController as homePageCtrl"
})
.state("Dashboard",{
url:"/dashboard",
templateUrl:"site/dashboard.html",
controller:"DashboardController as homePageCtrl"
})
)}
Explanation:
you have to inject $urlRouterProvider service in your config to make by default route to specific state.
in this example we make`
$urlRouterProvider.otherwise("/home");
so it will route to url "/home" which is url specified for homePage state.
So it will load respective html page of that state i.e homePage.html.
if you want other static page to be your default page when your project is loaded,just specify its url in $urlRouterProvider().
Don't forget to inject $urlRouterProvider service.
Also in your index.html add all your custom css files if it overrides the boootstrap css files then make sure that add your ids to your html and specify css for that.
Hope i have cleared your issues.
I did this by keeping the two projects completely separate. When I deploy the projects to my server, I put the Angular app into a sub-directory of the landing page project.
To do this, you need to tell the Angular app that it's running in a sub-directory, and not at the root of the site. At deploy time I have a gulp task modify the <base href="/"> tag in the Angular app's index.html so it looks like this: <base href="/sub-directory-name/">
I use the gulp task so that when I'm developing locally I can run the Angular app from the root, not the sub-directory.
Modifying the <base> tag means you won't have to change any of the URLs in your Angular app to reflect it's new location in the sub-directory.
Finally, my web server (nginx in my case), is configured to serve the landing page at the root, and the single page app from the sub directory.
I have an AngularJS application that is injected into 3rd party sites. It injects dynamic content into a div on the 3rd party page. Google is successfully indexing this dynamic content but does not appear to be crawling links within the dynamic content. The links would look something like this in the dynamic content:
Link Here
I'm using query parameters for the links rather than an actual url structure like:
http://www.example.com/support/title/Example Title/titleId/12345
I have to use the query parameters as I don't want the 3rd party site to have to change their web server configuration to redirect unfound URLs.
When the link is clicked I use the $locationService to update the url in the browser and then my angular application responds accordingly. Mainly it shows just the relevant content based on the query params, sets the page title and meta description.
Many of the articles I have read use the route provider in angularJS and templates but I'm not sure why this would make a difference to the crawler?
I have read that google should view urls with query parameters as separate pages so I don't believe that should be the issue:
https://webmasters.googleblog.com/2008/09/dynamic-urls-vs-static-urls.html
The only things I have not tried are 1. providing a sitemap with the urls that have the query parameters and 2. adding static links from other pages to the dynamic links to help google discover those pages.
Any help, ideas or insights would be greatly appreciated.
This happens because google crawlers are not able to get the static html from your url since your pages are dynamically rendered with Javascript, you can achieve what you want using the following :
Since #! is deprecated, You can tell google that your pages are rendered with javascript by using the following tag in your header
<meta name="fragment" content="!">
On finding the above tag google bots will request your urls with the _escaped_fragment_ query parameter from your server like
http://www.example.com/?_escaped_fragment_=/support?title=Example Title&titleId=12345
Then you need to rebuild your original url from the _escaped_fragment_ on your server and it will look like this again
http://www.example.com/support?title=Example Title&titleId=12345
Then you will need to serve the static HTML to the crawler for that url.
You can do that using a headless browser to access the url. Phantom.js is a good option to render your page using the javascript and then give the contents into a file to create a HTML snapshot of your page. You can save the snapshot as well on your server for further crawling, so when google bots visit can you can directly serve the snapshot instead of re-rendering the page again.
The web crawler might be running at a higher priority than the AngularJS interpretation of your dynamic links as the web crawler loads the page. Using ng-href makes the dynamic link interpretation happen at a higher priority. Hope it works!
If you use urls with #
Nothing after the hash in the url gets sent to your server. Since Javascript frameworks originally used the hash as a routing mechanism, that's a main reason why Google created this protocol.
Change your urls to #! instead of just using #.
angular.module('myApp').config([
'$locationProvider',
function($locationProvider) {
$locationProvider.hashPrefix('!');
}
]);
This is how Google and bing handle the ajax calls.
The documentation is mentioned here.
The overview as mentioned in the docs is as follows
The crawler finds a pretty AJAX URL (that is, a URL containing a #! hash fragment). It then requests the content for this URL from your server in a slightly modified form. Your web server returns the content in the form of an HTML snapshot, which is then processed by the crawler. The search results will show the original URL.
Step by Step guide is shown in the docs.
Since the Angular JS is designed for the Client Side so you will need to configure your Web server to summon a headless html browser to access your web page and deliver a hashbang url which will be given to the special google URL.
If you use hashbang URL then you would need to instruct the angular application to use them instead of regular hash values
App.config(['$routeProvider', '$locationProvider', function($routes, $location) {
$location.hashPrefix('!');
$routes.when('/home',{
controller : 'IndexCtrl',
templateUrl : './pages/index.html'
});
as mentioned in the code example here
However if you do not wish to use hashtag url but still inform the google of the html content but still want to inform the google then you can use this meta tag as this
<meta name="fragment" content="!" />
and then configure the angular to use the htmlURL's
angular.module('HTML5ModeURLs', []).config(['$routeProvider', function($route) {
$route.html5Mode(true);
}]);
and then whichever method to be installed via module
var App = angular.module('App', ['HashBangURLs']);
//or
var App = angular.module('App', ['HTML5ModeURLs']);
Now you will need a headless browser to access the url
You can use phantom.js to download the contents of the page ,run the javascript and then give the contents into a temporary file.
Phantomrunner.js which takes any url as input,downloads and parses the html into DOM and then checks the data status.
Test each page by using the function defined here
SiteMap can also be made as well as shown in this example
The best feature is you can use search console of verify your site url using
Google search console
Full attribution goes to the website and the author mentioned in this site
.
UPDATE 1
Your crawler needs the pages as -
- com/
- com/category/
- com/category/page/
By default, however, Angular sets your pages up as such:
- com
- com/#/category
- com/#/page
Approach 1
Hash bang allows Angular to know which HTML elements to inject with JS which can be done as mentioned before but since it has been depericated hence the another solution would be the following
Configure the $locationProvider and set up the base for relative links
You can use the $locationProvider as mentioned in these docs and set the html5mode to true
$locationProvider.html5Mode(true);
This lets Angular change the routing and URLs of our pages without refreshing the page
Set the base and head of your document as <base href="/">
The $location service will automatically fallback to the hashbang method for browsers that do not support the HTML5 History API.
Full attribution goes to the page and the author
Also to mention there are also some other measures and tests that you can take care of as mentioned in this document
I am writing a web app similar to dropbox and gdrive, i fetch ids of file based on that it will be able to navigate from page to page, folder to folder, e.g /abc to abc/abc... All i need to do it from client side. I made it simple using AngularJS Routing(ui-router).
Here is my code
$stateProvider.state('dashboard.sync.root', {
url: "/*path",
templateUrl: "root.html",})
here user can navigate like http://myweb/dashboard/sync/root/abc or http://myweb/dashboard/sync/root/abc/.../../
while traversing from page to page the root.html(template) goes on changing.
Problem here is when I traverse back and forth, it doesnt store previous view. when i click back and forward button in browser. Any Solution Appreciated
You can use 3 different files to maintain your app:
header.html
body.html
footer.html
And use ng-view in body to include using your routes.
Angular.js routes create URLs such as these:
http://cooldomain.com:3000/#/search
http://cooldomain.com:3000/#/docs
In my docs url, I would like to have one long page with <a name="sdsds"> sections and a traditional table of content with anchor links so that the user can hop up and down the page
Conceptually the table of contents would produce lots of invalid URLs such as http://cooldomain.com:3000/#/docs#coolAPIFunction which of course wouldn't work because of the double hash
So- is it possible to use anchor links in Angular.js applications that have routes?
You could enable html5 pushstate and get rid of the # in your routes. You can do so by adding this to your .config
$locationProvider.html5Mode(true);
However, be aware that now there will not be a distinction between Angular routes vs. server requests. You'll have to config your server to deliver the appropriate static html file (e.g. index.html) for that url.