I am following the angular-meteor tutorial at: http://www.angular-meteor.com/tutorials/socially/angular1/routing-and-multiple-views
I understand most of the routing, but I do not see where all the parts tie together. So here's my thought process.
I the routes, I notice the :partyId.
.state('parties', {
url: '/parties',
template: '<parties-list></parties-list>'
})
.state('partyDetails', {
url: '/parties/:partyId',
template: '<party-details></party-details>'
});
And in < parties-list >, I can see "this.partyId = $stateParams.partyId" being defined. #1. How is :partyId and $stateParams.partyId related? #2. The directive is called "partyDetails" whereas the template is < party-details >... is this an implied name given by Angular?
angular.module('socially').directive('partyDetails', function () {
return {
restrict: 'E',
templateUrl: 'party-details.html',
controllerAs: 'partyDetails',
controller: function ($scope, $stateParams) {
this.partyId = $stateParams.partyId;
}
}
});
Next... inside the party-list.html page (NOT party-details.html), there is a ui-sref link:
<li ui-sref="partyDetails({ partyId: party._id })" ng-repeat="party in partiesList.parties">
{{party.name}}
<p>{{party.description}}</p>
<button ng-click="partiesList.removeParty(party)">X</button>
</li>
But in the < party-list > directive there is no mention of any variable or function called "partyDetails". #3.What is the ui-sref referencing? How does it compare to "< a href="/parties/{{party._id}}" >" that is used further in the tutorial.
#4. Finally, is there anything that I should know about Meteor or Angular UI.Router in regards to things that are implied/abstracted away?
Thank you for your time! :)
It's same. If you declare parameters in query string like :partyId, you will received an object stateParams with keys are these parameters and values are proportional string in your segment of url.
It's coding conversation of Angular Js. You can check it out for more example.
https://docs.angularjs.org/guide/directive
Not problem if you use correct anywhere. But what is happened if you want change link or url structure? Example: href="/home" appear more than 20 html pages. And you want change all to "/homepage". Why???. With router, you need only change url state in the router.js file. Ok?
Angular-meteor is one of ways help you build your apps with angular. So everything related angular, you can find separate. Example you can read about angular ui router or all package of angularui in this link https://angular-ui.github.io
Related
I'm just learning Angular and have a very basic app set up. When rendering some data via the templateUrl property of a route, what would be the best way to include a sub-controller in the returned template? For example, including a "createOrEditItem" template at the bottom of a "viewItem" template so that the "createOrEditItem" can be reused on its own later?
I've tried putting a div in the template with its ng-controller attribute set to a controller name that I've defined at the app level, but it's not being activated. Should this be done with a directive instead to make it instantiate when the master controller has its contents set, or am I missing something more fundamental?
yes, as mentioned in the later part of the question, you should be using a directive. Or, if using AngularJS >= v1.5, component should be the choice because they are pluggable and works well with nesting too.
Note that for the route also, you can directly use a component like this:
var myMod = angular.module('myMod', ['ngRoute']);
myMod.component('home', {
template: '<h1>Home</h1><p>Hello, {{ $ctrl.user.name }} !</p>',
// ^^^^ other components can be used here
controller: function() {
this.user = {name: 'world'};
}
});
myMod.config(function($routeProvider) {
$routeProvider.when('/', {
template: '<home></home>'
});
});
Now, as the comment suggests, you can freely use other components in the template of home component.
Hope this helps a bit!
A directive can be used.
Another option is to use a seperate view/route. So when you add a ui-view tag, you could define your view and route.
This is explained here:
https://scotch.io/tutorials/angular-routing-using-ui-router
I posted a question recently about how to set parameters in the URL with Angularjs so that they could be preserved on page reload. But it caused a problem with Google Maps.
I am using ngRoute to navigate around my application. And the problem that I've experienced with setting parameters in the URL, was that every time I would set a parameter (be it $location.search() or just a plain old window.location.hash='something'), the Google Maps map would get unloaded. I tried changing parameter names, because I thought Google Maps listens to some of those options by default. But that wasn't the case.
Once I got rid of the ngRoute code completely, and instead of the ngView directive, I included my pages with ng-include, the map didn't get unloaded anymore when I manipulated the parameters.
I'm not that good as to know exactly what or why is going on, but I would guess that ngRoute thinks it has to compile my template file again because "something" changed in the URL. So what I would like, is to explain to ngRoute somehow, that if the part after ? changed, then it shouldn't try to compile my template file again (and subsequently destroy the loaded Google Maps), because those are just my additional options. But if the part before ? changed, then that's fine, because then the page changed.
Or, is there another, better, more Angular-way of getting around this issue?
This is my ngRoute configuration:
app.config(function($httpProvider, $routeProvider) {
// Routing
$routeProvider.when("/", {
redirectTo: "/Map"
}).when("/Map", {
controller: "MapController",
templateUrl: "tpl/view/map.html"
}).when("/Table", {
controller: "TableController",
templateUrl: "tpl/view/items-table.html"
}).otherwise({
templateUrl: "tpl/view/404.html"
});
});
This is my code for changing pages:
$scope.navigate = function(location) {
$location.path(location);
};
And this is how I would set up a custom GET parameter, as per the code from my other Stackoverflow question:
var params = $location.search();
params.source = source.filename;
$location.search(params);
You're looking for the reloadOnSearch property.
app.config(function($httpProvider, $routeProvider) {
...
}).when("/Map", {
controller: "MapController",
templateUrl: "tpl/view/map.html",
reloadOnSearch: false
})
...
});
https://docs.angularjs.org/api/ngRoute/provider/$routeProvider
I searched through many posts already, but still can't make run a very basic custom directive since the templateUrl is not resolved correctly.
I've got an AngularJSController with an Index - action (asp.net MVC), calling View/AngularJS/Index.cshtml, very basic. In there, I call a custom directive:
<product-title></product-title>
which is outlined liked that:
app.directive('productTitle', function () {
return {
restrict: 'E',
// ends up with wrong url '{root-path}/AngularJS/AngularJSTemplates/ProductTitle'
templateUrl: 'AngularJSTemplates/ProductTitle'
}
});
As you can see, it should call the controller AngularJSTemplatesController (asp.net MVC) with the action method ProductTitle. This will return my partial for angularJS. And here is the problem: AngularJS calls {root-path}/AngularJS/AngularJSTemplates/ProductTitle instead of {root-path}/AngularJSTemplates/ProductTitle...
What I am missing here? Do I really need to define the root-path somewhere as a javascript-global and use it for absolute paths?
You may need to define the base url, see the documentation on using Relative links here
just replace directive with follwing directive :
app.directive('productTitle', function () {
return {
restrict: 'E',
// ends up with wrong url '{root-path}/AngularJS/AngularJSTemplates/ProductTitle'
templateUrl: 'AngularJS/AngularJSTemplates/ProductTitle'
}
});
i think directive cant find your template. AngularJS/AngularJSTemplates/ProductTitle is the relative url for your template. i think it wil work.
I have a route defined as
$routeProvider.when('/:culture/:gameKey/:gameId/closed', { templateUrl: '/templates/tradingclosed', controller: TradingClosedCtrl });
I would like angular to include the "culture" parameter when requesting the template somehow, so I can serve a translated template.
Is this possible?
If I'm reading this correctly you'd like to somehow use the culture parameter from the url route to determine which location to retrieve your template.
There may be a better way but this post describes retrieving the $routeParams inside a centralized controller with ng-include to dynamically load a view.
Something similar to this:
angular.module('myApp', []).
config(function ($routeProvider) {
$routeProvider.when('/:culture/:gameKey/:gameId/closed', {
templateUrl: '/templates/nav/urlRouter.html',
controller: 'RouteController'
});
});
function RouteController($scope, $routeParams) {
$scope.templateUrl = 'templates/tradingclosed/' + $routeParams.culture + '_template.html';
}
With this as your urlRouter.html:
<div ng-include src="templateUrl"></div>
You can define the controller you want to load in your views using ng-controller and access the $routeParams for the additional route parameters:
<div ng-controller="TradingClosedCtrl">
</div>
I've posted similar question with working Plnkr example of solution like #Gloopy suggested.
The reason why you can't implement that without ng-include is that routing is done in 'configuration' block, where you can't inject any values (you can read about these blocks in Modules documentation, section Module Loading & Dependencies
If you want not to introduce new scope, you can replace ng-include with my stripped version of ng-include directive, that do absolutely same that ng-include does, but do not create new scope: source of rawInclude directive
Hope that solution will satisfy your use case.
I have a working Angular.js app with HTML5 mode enabled.
$location.Html5mode(true).hashbang("!");
What I want to achieve is to get some URLs or <a> tags to do the normal browsing behaviour instead of changing the URL in the address bar using HTML5 history API and handling it using Angular controllers.
I have this links:
<a href='/auth/facebook'>Sign in with Facebook</a>
<a href='/auth/twitter'>Sign in with Twitter</a>
<a href='/auth/...'>Sign in with ...</a>
And I want the browser to redirect the user to /auth/... so the user will be then redirected to an authentication service.
Is there any way I can do this?
Adding target="_self" works in Angular 1.0.1:
<a target="_self" href='/auth/facebook'>Sign in with Facebook</a>
This feature is documented (https://docs.angularjs.org/guide/$location - search for '_self')
If you're curious, look at the angular source (line 5365 # v1.0.1). The click hijacking only happens if !elm.attr('target') is true.
An alternative to Fran6co's method is to disable the 'rewriteLinks' option in the $locationProvider:
$locationProvider.html5Mode({
enabled: true,
rewriteLinks: false
});
This will accomplish exactly the same thing as calling $rootElement.off('click'), but will not interfere with other javascript that handles click events on your app's root element.
See docs, and relevant source
This is the code for turning off deep linking all together. It disables the click event handler from the rootElement.
angular.module('myApp', [])
.run(['$location', '$rootElement', function ($location, $rootElement) {
$rootElement.off('click');
}]);
To work off the Nik's answer, if you have lots of links and don't want to add targets to each one of them, you can use a directive:
Module.directive('a', function () {
return {
restrict: 'E',
link: function(scope, element, attrs) {
element.attr("target", "_self");
}
};
});
I've run into the same issue a few times now with angular, and while I've come up with two functional solutions, both feel like hacks and not very "angular".
Hack #1:
Bind a window.location refresh to the link's click event.
<a
href=/external/link.html
onclick="window.location = 'http://example.com/external/link.html';"
>
The downside and problems with this approach are fairly obvious.
Hack #2
Setup Angular $routes that perform a $window.location change.
// Route
.when('/external', {
templateUrl: 'path/to/dummy/template',
controller: 'external'
})
// Controller
.controller('external', ['$window', function ($window) {
$window.location = 'http://www.google.com';
}])
I imagine that you could extend this using $routeParams or query strings to have one controller handle all "external" links.
As I said, neither of these solutions are very satisfactory, but if you must get this working in the short term, they might help.
On a side note, I would really like to see Angular support rel=external for this type of functionality, much like jQueryMobile uses it to disable ajax page loading.
To add to Dragonfly's answer, a best practice I have found to limit the number of target="_self" attributes is to never put the ng-app attribute on the body tag. By doing that you are telling angular that everything within the body tags are a part of the angular app.
If you are working within a static wrapper that should not be affected by angular, put your ng-app attribute on a div (or other element) that surrounds only the location your angular app is going to be working in. This way you will only have to put the target='_self' attribute on links that will be children of the ng-app element.
<body>
... top markup ...
<div ng-app="myApp">
<div ng-view></div>
</div>
... bottom markup ...
</body>
In your routes try:
$routeProvider.otherwise({})