AngularJS - Navigating inside a directive/component - javascript

I have a component (directive) which should be used as a stand alone component by other applications (bower component, for example). I want to add navigation inside my directive (using ngRoute or ui-router) - but this could conflict with the host application navigation (if it uses one).
For example:
Main application has a routing for my component:
http://address.com/route-to-my-component
Now, inside my application I should have an inner route (I am not aware of the main application routing):
$routeProvider.
when('/route1', {
template: `<comp1></comp1>`
}).
when('/route2', {
template: `<comp2></comp2>`
}).
otherwise({
redirectTo: '/route1'
});
There are several problems with this solution:
Main application might not recognise my routing, so it will fall to its default route.
I cannot know what is my parent router solution, which makes it hard for me to configure my own routes.
Is there a solution to this problem?
Thanks
EDIT
I ended up with two optional solutions:
Using angular-widget, which is a great solution but is too complex for my case (it will be an overkill for me)
Using history.pushState.
So, I implemented the second option, like this:
When the use click the navigation (inside my component), I do pushState:
history.pushState({someData}, 'some-title', url );
And I added an event for user's pressing the back button:
window.onpopstate = function(event) {
//My back logic here
}.bind(this);
It is kind of hackey solution but it was perfect to my situation and needs.

Related

How can I execute Angular code without bootstrapping?

All manual bootstrapping examples use the following pattern:
angular.module('myApp', []);
angular.bootstrap(document, ['myApp']);
However, I don't need angular to look at the document, I just need to open a popup using ui-bootstrap module.
The best I managed to do was the following:
$("...").click(function() {
angular.module("pp", ["ui.bootstrap"])
.config(["$modal", function($modal) {
$modal.open({
template: "Hello!"
});
}]);
angular.bootstrap(null, ["pp"]);
});
However, that will re-bootstrap angular every time, re-create the same module over and over, and above all that it doesn't work - configs run alongside provider initialization, thus there is no $module dependency available at that time.
Basically, I am trying to incorporate angular into existing application without creating significant disturbance in current structure. I want angular to manage a single popup, nothing else for now, so normal bootstrap & controller way doesn't seem to be the best option.
Is there some way to run that modal without doing global angular bootstrap?
Have you tried bootstrapping angular to the whole document and simply not using it for anything but the modal call? Unless there are namespace conflicts with your current code, it seems like this would allow you to use Angular functions wherever you please without bootstrapping every time.
Why not use just Bootstrap without the angular wrapper?
The angular directives only wrap the original bootstrap modals with some extra stuff.
Seems to me a bit pointless to include Angular + Bootstrap + UI Bootstrap when you can achieve the same just with Bootstrap itself.

how do i redirect a user in ember.js without changing the window.location

In ember.js (I am using 1.1.2) How do I 'send/redirect' a user to a particular url programmatically (without forcefully changing window.location.href).
I have a hybrid application, where we run some legacy code and an Ember "app". In order to make the boundaries really explicit, we created a simply library we called the 'LegacyBridge'. It helps external code call into Ember without having to know too much about the internals. It's also a nice way to limit what external code can do with your Ember App, since there's a lot they could do and it's a good idea to keep limit the options.
Anyway, here's what you could do:
var transitionTo, getContainer;
var getContainer = function() {
return App.__container__;
};
var transitionTo = function(route) {
var router = Ordering.__container__.lookup('router:main');
router.transitionTo(route);
};
this.App.LegacyBridge = {
transitionTo: transitionTo
};
Then somewhere in the non-Ember code:
App.LegacyBridge.transitionTo('posts/1');
This is certainly hacky. In general I wouldn't lookup things directly from the container, but since it's well encapsulate and this is more of an exceptional use case I can live with it.
BTW, this is better than changing the URL, since everything will work even if your router changes the location strategy from history to hash or none, if the rootUrl changes or for browsers not supporting pushState (Ember now will fallback to hash)
Hope this helps.
Check out the guide on redirection.
Ember allows you to transition to a route via it's name or it's URL:
router.transitionTo('post', post)
router.transitionTo('/posts/1')
EDIT:
I'm not sure of a good way to attain a reference to the router from outside your Ember application other than the very discouraged App.container.lookup('router:main'). If you can still handle this UI interaction within your Ember app, it's as simple as adding an action (a method inside the actions hash) to your ApplicationRoute.
Manipulating window.location is probably the 'cleanest' way of triggering a transition from outside your Ember app.

What is a recommended way to switch the application template in Ember.js?

I've been playing around with Ember.js, and something that I couldn't easily find was how to switch out the base application template. For example, let's say that my application has 2 core layouts, one that is more presentational when the user is learning about the application before registering, and another that is the logged-in layout, the web application itself.
What is the recommended way to change which layout template is going to be used on a conditional basis?
UPDATE
From the solution, here is what I am doing: https://gist.github.com/eliperelman/8310055
I'd use layoutNameBinding in the ApplicationView. This answer should get you started: https://stackoverflow.com/a/13980055/1234490 (start reading at 'EDIT').
You could do something like this:
App.ApplicationRoute = Ember.Route.extend({
renderTemplate: function() {
if(... authenticated ...) {
this.render('authenticated');
else{
this.render('guest');
}
}
});
This would change the entire application template, but keep the same application controller for both templates (you can pass a hash into the render method with a controller to use).

Misunderstanding of Single-Page Routing in Angular

I think I have a fundamental misunderstanding about the way angular intercepts my routes in a single-page application.
My problem, I think, is pretty simple. When I enter the url:
localhost:3000/streams/
I would like to load the 'streams' page. The way I thought it works is as follows:
My express server receives the request, and answers with a layout.
app.get('/streams/',function(req,res){
res.render('layout');
})
My layout page is rendered. It calls a client app.js and has ng-view.
Angular intercepts the '/streams/' path, and then makes a call for the 'streams' template. Like this:
$routeProvider
.when('/',
{
templateUrl: '/templates/mainpage'
}
)
.when('/streams/',
{
templateUrl: '/templates/streams'
}
)
For some reason, reality is very very different.
When I load '/streams', angular retrieves /templates/streams, and
when I load '/streams/, angular retrieves /templates/mainpage.
Why?
This misunderstanding has been trolling me for days now...
Any help will be rewarded with 5 quanta of good energy.
Thanks.
It turns out that the real issue was a little different.
It's not, as was described, that Angular didn't know that I'm referring to 'streams', when I load 'streams/', it's that html had a relative base.
Basically, this relative base made it seem as though I have already found a template, namely, '/streams', and am now retrieving another one, namely, '/'. This issue can be simply resolved by adding the root base in your html.
<base href="/">
This should do it.

Angular sub-views

I google a bit about the topic but I couldn't get a clear answer on the subject, so apologies if this seems a pretty beaten down question. I've started with Angular not long ago, and I really want to be on the good path.
The application is bootstraped by app.js which defines the routes in the configuration. The index.html has a body with a ng-app directive an just a div inside with a ng-view.
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainController'
})
.otherwise({
redirectTo: '/'
});
This main.html and controller are the bulk of the app, which is quite simple.
Now I wanted to have a header, which either shows Login or the information from the user. I though that should be another Controller and another View, since the header should encapsulate all that code instead of polluting the main view.
What should I do?
I could remove the ng-app and create two different controllers for the header and the main app, but then I don't know how to associate each view to each ng-controller like the routeProvider is doing, although if I don't mind writing all the html inline, this should work. I would also lose routing which I don't really want to.
I could just create a ng-controller=headerController inside the app and still have the code inline. Is there an option to associate a template with a controller without the route definition?
What I'm currently going to do until I have a better option is to add all of this logic to the mainController. I just feel that I'm building big blocks instead of small ones that I can just compose. Imagine I do three more routes that need a header. Using option 1) or 2) I would have to write the template html for the header again in those views.
I would appreciate any links or help for this matter, I'm really curious how to approach this in a module fashion.
Thank you in advance.
I could remove the ng-app and create two different controllers for the header and the main app, but then I don't know how to associate each view to each ng-controller like the routeProvider is doing, although if I don't mind writing all the html inline, this should work. I would also lose routing which I don't really want to.
You will just write two different modules which have the same routeConfig and things will probably work. However, I do not think that it is the best solution in this case.
To answer your second question:
I could just create a ng-controller=headerController inside the app and still have the code inline. Is there an option to associate a template with a controller without the route definition?
You can use ng-include to include the template:
<body ng-app="MyApp">
<section ng-include="'header.html'" ng-controller="HeaderController"></section>
<ng-view></ng-view>
</body>
Moreover, you can keep the template inline by using either the $templateCache or by using <script> tag.
You can use ng-include to insert your template. I personally like to use ui-router

Categories

Resources