canActivate issue with durandal 2.0.1 - durandal

I downloaded Durandal 2.0.1 StarterKit and I am using it for a web project. I worked with it for a while now.
In one of my viewmodels I am using the routing with id in the url: route: 'test/:id'. Since I want to protect against random id inputs from the user, I am using the canAvtivate function, in which I perform some checks.
When I'm trying to access the route from another route the canActivate function is evaluated before activating, but when i just change the id value in the url the function is not called. It happens the same if I say router.navigate("#/test/44"); from within that view.
Is this desired behavior?

This is a bit of a guess as I haven't played much with parameterized routing yet, but perhaps the active module is being reused? Does the section "Module Reuse" at the link below apply in your situation?
http://durandaljs.com/documentation/Using-The-Router/
Perhaps you can work around this by implementing canReuseForRoute

Related

Vue page cannot open after refreshing the page

I added the routes dynamically to the router and I can visit all pages with router-view. However, when I try to refresh the page I cannot visit the page again although the URL is the same. It is http://localhost:8081/me.
this.$router.addRoute("Main", {
path: '/me',
name: 'Me',
component: () => import(`#/components/Me.vue`)
});
As I said, I can normally visit the page "Me", but when I refresh it, I cannot see its content anymore with the warning:
[Vue Router warn]: No match found for location with path "/me"
I tried to create router with createWebHistory("/") after reading the cause of the error but nothing seems to change. I will appreciate any help.
There are two reasons why this would happen.
First serving SPA application from the server.
Make sure that your back-end is set to serve index.html file for all routes since back-end server is unaware of the routes set by client-side router. Something like express-history-api-fallback-middleware can help is using Node.js/Express.js.
Second problem is that of using addRoute.
As you described, the problem could be that Vue router is taking routing decision before your code in components/common/LeftMenu.vue is getting executed which is responsible for calling addRoute(). Ensure that this code is called before routing decision is being made. Best way would be to move this logic in top-level application component. And, if you can move that to top-level components, that means you can try to declare all routes while defining the router.
Why that should be done?
Using addRoute is not necessarily an anti-pattern but having to rely on addRoute is often code smell. You would really need it in extremely rare scenarios. Routing is a high-level architectural concern for your application and thus better to be declared upfront somewhere at top-level module even before application is getting initialized. Low level components should not attempt to manipulate routing data structure (violation of DIP principles).
One scenario where you might be tempted to use addRoute is taking decision after some data manipulation by the component with addition of some API call. That seems legitimate need but then to address that there are better ways. Considering using route guards (guards support async resolution too!) and prevent user from entering the view till the guard is resolved successfully.

How to consume a graphql API with Vue

Pretty simple you'd think given the popularity of both, but I am encountering a few hurdles.
I am using scaphold.io to be able to quickly show off a working UI. That is, if Vue can interact with Scaphold.
I have investigated two resources:
https://github.com/kristianmandrup/vue2-apollo-scaphold
Which seems to be a Scaphold production. Tried it. Many, many vague bugs.
Then there is also:
https://github.com/Akryum/vue-apollo
But this is too much. I don't need a server, the server is on Scaphold.
I also tried building the whole thing up by using the tutorial on howtographql, but this one is also outdated.
Ideally I want to instantiate an as up to date Vue 2 app using (I guess) the npm vue-cli, then install only the required apollo (or whatever, but I guess apollo) add-ons that I need. The minimum.
Shouldn't be too hard, I'll figure it out eventually, but some help is more than welcome.
You can consume a graphql api using your favorite regular request module (ajax, fetch, axios). Take the scalphold docs for example, but in the callback do this.vueUserData = body.data.getUser;
instead of
console.log(JSON.stringify(body, null, 2));
(edited to add one gotcha I remembered: if you encounter a problem where the callback doesn't know that this is supposed to be the component, you can do var self = this before the request function, then reference self.vueUserData instead.)

Symfony - fallback to another application if Symfonfy app can not handle the request

We have an old Yii application along with new Symfony one.
The basic idea is simple - I need to check if there is a route matching in Symfony application then it is cool, if not then bootstrap Yii application and try to handle the request with it.
The main idea to not instantiate AppKernel (and do not load autoload.php - since there is two different autoload.php for each project) before I am sure there is route matching.
Can I do it somehow?
We've done this before with legacy applications.
There are two approaches you can take.
Wrap your old application inside a symfony project (recommended).
Unfortunately this will indeed load the symfony front-controller and kernel. No way around that. You need to make sure that symfony can't handle the request and to do that the kernel needs to be booted up.
Use sub-directories and apache virtual hosts to load one application vs the other as needed.
Given option 1,
You can either create your own front controller that loads either symfony or yii by reading routes (from static files if using yml or xml, or annotations which will be more complex) OR EventListener (RequestListener) that listens to the HttpKernelInterface::MASTER_REQUEST and ensures that a route can be returned.
Creating your own front controller is the only way that you can make it not load the symfony kernel, but it will require you to write something that understands the routes in both frameworks (or at least symfony's) and hands off the request appropriately.
Event listener example:
public function onkernelRequest(GetResponseEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
... Code to continue normally, or bootstrap yii and return a custom response... (Can include and ob_start, or make an http request, etc)
}
public function getSubscribedEvents()
{
return [
KernelEvents::REQUEST => ['onKernelRequest']
];
}
As you see, the kernel needs to be booted to ensure symfony can't serve the route. Unless creating your own front controller (as stated above).
A third approach would be to create a fallback controller, which would load up a specified URL if no route was found within symfony. Although this approach is generally used for legacy projects that lack a framework and use page scripts instead of proper routes, and definitely requires the use/help of output buffering.
The EventListener approach gives you the opportunity to create a proper Request to hand off to yii, and using what is returned to create a Response as proper symfony object (can also use ob or other options).
Thank you.
This is an alternative to vpassapera's solution -http://stovepipe.systems/post/migrating-your-project-to-symfony

How does one use :wildcards in parent routes?

I'm building an express app in express 4.0 (rc3), since I'm starting from scratch and in development for a while, but if there's a way to do this in 3.0, that'd be welcome too.
What I want is a set of comment REST routes that I can attach to other routes in my API. So:
/posts/:postID/comments/:commentID
/profiles/:profileID/comments/:commentID
The way I was doing it was to encapsulate the comment routes into a module, including a buildRoutes(router) function in the module.
Then I can do app.use('/api/comments', commentController.buildRoutes(express.Router())) in my main server definition, and then in my profile module's buildRoutes(router), I can do
buildRoutes = function(profileRouter)
.... build the basic CRUD routes ...
profileRouter.get('/:profileID', show)
profileRouter.use('/:profileID', commentController.buildRoutes(express.Router()))
It seems like only the .VERB methods actually replace :wildcards in the route, and not the .use one. I could always muddle through with a piece of custom middleware that goes on a /api/profiles/* and maps the appropriate URL parameters into req.fields, but I want to make sure that this is actually required.
So this wasn't particularly easy to do the way I originally intended. However, I just avoided the entire problem by reframing my buildRoutes method to accept a baseURL and a router argument. Instead of modularizing it completely, now I say, profileController.buildRoutes('/api/profiles/', router) which in turn calls commentController.buildRoutes('/api/profiles/:profileID/comments', router), and so on.
It's not terribly satisfying (I would rather encapsulate path/routing information and hide that from the controller) but it works.

Backbone.js fetch() ajax error

I am putting together a basic CRUD system for a project, and we've decided to bundle in Backbone.js & CoffeeScript to abstract more of our JavaScript functionality. The learning curve has been pretty steep for me, since I'm not much of a JS pro.
At the moment, I'm just trying to pull a record. Any record. So I've rigged a dummy route to supply a 'products' record set via JSON, to see how it renders, before I go forward.
window.Product = Backbone.Model.extend
initialize: -> console.log this
window.Products = Backbone.Collection.extend
model: Product
initialize: -> console.log this
url: '/dummy'
So, in the console, I type:
product = new Product()
And it seems to render the product just fine. But when I type:
product.fetch()
It returns:
TypeError: Cannot call method 'ajax' of undefined
I tried the same thing with the Collection.
products = new Products()
products.fetch()
TypeError: Cannot call method 'ajax' of undefined
I've made other parts (view renders, etc.) work just fine, but this ajax error is getting at me repeatedly. I've spent hours looking through different documentation (including the official ones, and all the information I could trail to from the wiki), trying out the code in plain JavaScript as well as CoffeeScript, implementing different scopes (with/without window namespacing), etc. There's nothing on Google.
This must be something ridiculously simple that I should probably just know, but I can't figure it out for the life of me. Or it was the one spot of the documentation that I missed. Can anyone tell me what I'm doing wrong?
#Ironchamber: In order to use the Ajax method of Backbone, you must also supply a library that provides cross-browser Ajax support. Backbone is optimized to use either jQuery or Zepto. It looks to me from your error message that you're missing one of those.
The other solution is to call this at document ready:
Backbone.setDomLibrary(jQuery);
This way the file include order doesn't matter.