Angular state provider match cases in url (regex) - regex

I've created an SPA with multiple ui-views using the state provider.
I have a few url match cases, however I want to make them match not just on an explicit url, example:
app.config(function($stateProvider, paths) {
var base = paths.static.views + 'modules/';
$stateProvider
.state('home', {
url : '/',
views : {
'home' : {
templateUrl : base + 'home/_layout.html',
controller: function() {
console.log('home');
}
}
}
})
.state('foo', {
url : '/foo',
views : {
'foo' : {
templateUrl : base + 'foo/_layout.html',
controller: function() {
console.log('foo');
}
}
},
})
.state('bar', {
url : '/bar*',
views : {
'bar' : {
templateUrl : base + 'bar/_layout.html',
controller: function() {
console.log('bar');
}
}
},
})
.state('dog', {
url : '/dog*',
views : {
'dog' : {
templateUrl : base + 'dog/_layout.html',
controller: function() {
console.log('dog');
}
}
},
});
});
So if I navigate to /foo it works, however if my server has a re-write rule (which it does in some cases) it will re-write it to /foo/ and the match case no longer fires.
I've tried adding {url : '/foo*'} but that didn't work either.
I would really like to fix this!

Related

Add wildcard to the end of a URL after a specific word

I have a URL that looks like this:
https://localhost:8080/user/login
However, there is the ability to manually append query parameters so that the URL can look like this.
https://localhost:8080/user/login?ten=123456
So I need a wildcard with which everything is taken after the word 'login'.
My URLs are defined in within a constant object like this:
export const Constants = {
routing: {
home: '/',
userLogin: '/user/login',
}
..and are used like this:
const routing = Constants.routing;
const url = this.routing.userLogin
Naviagte to your url with the Router.navigate in your component
import { Router } from "#angular/router"
constructor(private router : Router){}
navigateToUserLogin(){
this.router.navigate([url], { queryParams: { ten: 123456 } });
}
You can use ActivatedRoute in your user-login component to extract the query params of the url
import { ActivatedRoute } from '#angular/router';
constructor(private route: ActivatedRoute) { }
ngOnInit(){
this.route.queryParams.subscribe(params=> { console.log(params); });
}
I don't now if i unstand your problem?
A regex to extract everything after the word 'login' would be:
(?<=login).*$
How to apply in Component:
public ngOnInit(): void {
let regex = new RegExp("(?<=login).*$");
const matches = regex.exec(window.location.href);
if(matches.length>0){
this.href=matches[0];
}
}
For routing with queryparams in angular you can use NavigationExtras with the queryParams property:
router.navigate(["user", "login"], { queryParams: { ten: "123456" } });
And using router link
<a [routerLink]="["user", "login"]" [queryParams]="{ ten: '123456' }">Login</a>

requirejs + django_select2

I'm building a wagtail / django app using requirejs as js assets combiner, for the site front end.
I'm using it because I've ever been in a kind of JS dependencies hell, where nothing works because of multiple versions of same libs loaded, from different django apps... (I don't even know if it is a good solution)
I've to tell that I'm not a JS expert, and I've none arround me :(
I'm using the good old templates to render the pages, not using angular, react, riot nor vue : I'm a pretty old school dev :)
I've already adapted some scripts to use require, but I'm stuck for now...
I've installed the django_select2 application, and I'm trying to adapt the django_select2.js asset.
I've loaded select2 through bower, and I've updaetd my config.js:
"shim": {
select2: {
deps: ["jquery"],
exports: "$.fn.select2"
}
},
paths: {
...
select2: "select2/dist/js/select2"
}
Then I'm trying to adapt the django_select2.js:
require(['jquery', 'select2'], function ($, select2) {
return (function ($) {
var init = function ($element, options) {
$element.select2(options);
};
var initHeavy = function ($element, options) {
var settings = $.extend({
ajax: {
data: function (params) {
var result = {
term: params.term,
page: params.page,
field_id: $element.data('field_id')
}
var dependentFields = $element.data('select2-dependent-fields')
if (dependentFields) {
dependentFields = dependentFields.trim().split(/\s+/)
$.each(dependentFields, function (i, dependentField) {
result[dependentField] = $('[name=' + dependentField + ']', $element.closest('form')).val()
})
}
return result
},
processResults: function (data, page) {
return {
results: data.results,
pagination: {
more: data.more
}
}
}
}
}, options);
$element.select2(settings);
};
$.fn.djangoSelect2 = function (options) {
var settings = $.extend({}, options);
$.each(this, function (i, element) {
var $element = $(element);
if ($element.hasClass('django-select2-heavy')) {
initHeavy($element, settings);
} else {
init($element, settings);
}
});
return this;
};
$(function () {
$('.django-select2').djangoSelect2();
});
}($));
});
I'm having a Mismatched anonymous define() when running my page in the browser...
I'me realy not a JS expert, I'm coding by trial and error... Could anyone help me with this ?
Thanks !
OK, I have an auto-response...
I've inherited the mixin:
class _Select2Mixin(Select2Mixin):
def _get_media(self):
"""
Construct Media as a dynamic property.
.. Note:: For more information visit
https://docs.djangoproject.com/en/1.8/topics/forms/media/#media-as-a-dynamic-property
"""
return forms.Media(js=('django_select2/django_select2.js', ),
css={'screen': (settings.SELECT2_CSS,)})
media = property(_get_media)
class _Select2MultipleWidget(_Select2Mixin, forms.SelectMultiple):
pass
Then I can use the widget:
class DocumentationSearchForm(forms.Form):
...
document_domains = forms.ModelMultipleChoiceField(required=False,
label=_('Document domains'),
queryset=NotImplemented,
widget=_Select2MultipleWidget)
I've set my config.js file for path:
requirejs.config({
paths: {
jquery: 'jquery/dist/jquery',
select2: "select2/dist/js"
},
shim: {
"select2/select2": {
deps: ["jquery"],
exports: "$.fn.select2"
}
}
});
Then I've overridden the django_select2.js file, to wrap the content in a require satement:
require(['jquery', 'select2/select2'], function ($) {
(function ($) {
var init = function ($element, options) {
$element.select2(options);
};
var initHeavy = function ($element, options) {
var settings = $.extend({
ajax: {
data: function (params) {
var result = {
term: params.term,
page: params.page,
field_id: $element.data('field_id')
}
var dependentFields = $element.data('select2-dependent-fields')
if (dependentFields) {
dependentFields = dependentFields.trim().split(/\s+/)
$.each(dependentFields, function (i, dependentField) {
result[dependentField] = $('[name=' + dependentField + ']', $element.closest('form')).val()
})
}
return result
},
processResults: function (data, page) {
return {
results: data.results,
pagination: {
more: data.more
}
}
}
}
}, options);
$element.select2(settings);
};
$.fn.djangoSelect2 = function (options) {
var settings = $.extend({}, options);
$.each(this, function (i, element) {
var $element = $(element);
if ($element.hasClass('django-select2-heavy')) {
initHeavy($element, settings);
} else {
init($element, settings);
}
});
return this;
};
$(function () {
$('.django-select2').djangoSelect2();
});
}($));
});
That's all, folks !

Don't request parent route's model

I've got a blog. Single blog-posts appear under /blog/post-title, a list of post under /blog/
Whenever I access a single blog-post like http://example.com/blog/post-title it also requests a list of posts from the parent-route:
For a single blog post the list of posts is not required. How can I prevent loading the parent's model (the list of posts)?
This is the router.js:
Router.map(function() {
this.route('base', { 'path' : '/' }, function() {
this.route('blog', { 'path' : 'blog/'}, function() {
this.route('post', { 'path' : ':permalink' })
})
})
})
1) Add a nested route 'index' under blog:
Router.map(function() {
this.route('base', { 'path' : '/' }, function() {
this.route('blog', { 'path' : 'blog/'}, function() {
this.route('index', { 'path': '/' });
this.route('post', { 'path' : ':permalink' })
})
})
})
2) Move your logic from 'blog' controller to 'blog.index', also move template logic from blog to blog.index.

ng-route does not make template requests

I have a django backed angular app that uses angular-route to resolve the urls
I have a login system that users a factory to verify the authorisation of a user, as mentioned here.
Here is a part of my app.js file
.factory('Auth', function (){
var user;
return {
setUser : function (u)
{
user = u;
},
isLoggedIn : function()
{
var User = false;
return User;
}
}
}
)
.config(
function($routeProvider)
{
$routeProvider
.when('/login', {
templateUrl : '/login',
controller:'LoginCtrl'
})
.otherwise('/')
}
)
.run(['$rootScope', '$location', 'Auth', function ($rootScope, $location, Auth) {
$rootScope.$on('$routeChangeStart', function (event) {
if (!Auth.isLoggedIn()) {
console.log('DENY');
event.preventDefault();
$location.path('/login');
}
else {
console.log('ALLOW');
$location.path('/home');
}
});
}])
I also have a watch set in my MainCtrl.
$scope.$watch(Auth.isLoggedIn,
function(value)
{
if(!value)
{
$location.path('/login')
}
else
{
$location.path('/home')
}
})
My issue is that, the /login template is never requested, even if I manually try /#/login, no errors in console as well.
Also, the location.$path('/login') is also not executed, as page stays right at requested
URL. However, DENY gets printed in the console log.
I suspect that it is due to the app.run attribute , as the template gets rendered if I remove the run attribute.
It is simple : "login" is a state, and you forbid access to any state if the user is not logged in !
You could just change this for example :
.run(['$rootScope', '$location', 'Auth', function ($rootScope, $location, Auth) {
$rootScope.$on('$routeChangeStart', function (event, toState, fromState) {
if (!Auth.isLoggedIn() && toState == 'login' ){
console.log('ALLOW');
}
else if (!Auth.isLoggedIn() && toState != 'login') {
console.log('DENY');
event.preventDefault();
location.path('/login');
}
else {
console.log('ALLOW');
$location.path('/home');
}
});
Also if you want to see a very complete auth system in angular.js, have a glance at this :
https://github.com/angular-app/angular-app/tree/master/client/src/common/security

Ember js to work with HATEOAS REST API

I have a REST endpoint "http://localhost:8080/customers" which I would like to hook to my Ember JS app.
App.Store = DS.Store.extend({
revision: 12,
adapter: DS.RESTAdapter.extend({
url: 'http://localhost:8080/customers'
})
});
REST Payload
{
"_links" : {
"search" : {
"href" : "http://localhost:8080/customers/search"
}
},
"_embedded" : {
"customers" : [ {
"id" : 2,
"firstName" : "Jim",
"lastName" : "Smith",
"_links" : {
"self" : {
"href" : "http://localhost:8080/customers/2"
}
}
}, {
"id" : 1,
"firstName" : "Jimmy",
"lastName" : "Jones",
"_links" : {
"self" : {
"href" : "http://localhost:8080/customers/1"
}
}
} ]
}
}
I keep on getting this error. This is my second week on Ember JS. To be honest this is a lot harder than I imagined. Not very easy to debug or understand.
Error while loading route:
TypeError: undefined is not a function
at App.CustomersRoute.Ember.Route.extend.model
Essentially you need to transform your data into this format using a custom serializer:
{
"customers" : [
{
"id" : 2,
"firstName" : "Jim",
"lastName" : "Smith"
}, {
"id" : 1,
"firstName" : "Jimmy",
"lastName" : "Jones"
}
]
}
You'll want to read https://github.com/emberjs/data/blob/master/TRANSITION.md which explains how to use extractSingle, extractArray, normalize, normalizeHash.
You're particular example looks close to the api's example:
http://emberjs.com/api/data/classes/DS.RESTSerializer.html#method_extractArray
App.CustomerSerializer = DS.ActiveModelSerializer.extend({
extractArray: function(store, type, payload) {
// do your own implementation and return that, or modify it slightly
// and do the default implementation
return this._super(store, type, payload);
},
});