I have a link with a route-href attribute pointing to one of my routes. This all works fine:
<a route-href="route: item; params.bind: {id: item.id}">${item.name}</a>
I've now created my own custom attribute route-popup which opens the route in a fixed overlay using <compose>, this too works fine:
<a route-popup="route: item; params.bind: {id: item.id}">${item.name}</a>
However, in order for users to be able to Ctrl+click and open items in new windows, I would like to use both route-href and route-popup on the link:
<a route-href="route: item; params.bind: {id: item.id}" route-popup="route: item; params.bind: {id: item.id}">${item.name}</a>
And then from my RoutePopupCustomAttribute class simply preventDefault() so that the route-href (or href it creates) is suppressed:
this.onClick = e => {
e.preventDefault();
e.stopPropagation();
this.ea.publish('route-popup:open', {route: this.route, params: this.params});
return false;
};
However, neither preventDefault, stopPropagation or returning false from my callback seems to work. Aurelia still follows the href and renders the new page.
How can I prevent the router from navigating to the route-href?
Edit: Ok so this is a little weird, I set up a gist.run to further explain the problem, however, on gist.run it actually does work :/ All that's needed is e.preventDefault(). The only difference in my code is that I'm using pushState: true in the router config, so I'm guessing that's it?
https://gist.run/?id=daf226363df8cdc777be718bff3a4f76
Yup, after further testing it turns out that when you use pushState: true it's not possible to preventDefault() whereas if you use hashChange: true it is.
Related
I want to go to my search page in nuxt myApp.com/search?parameter=1 from my main page. In the main page I can go to search page in two ways, by using a nuxt-link:
<NuxtLink
:to="`/search?parameter=${number}`"
>
</NuxtLink>
Or I can go with a method:
goToSearch() {
this.$router.push(`/search?parameter=${this.number}`);
},
When I use the nuxt-link and land on search page the url is correct with parameter: myApp.com/search?parameter=1
But when I use my method which is conencted to a button in the page and I land on search page the url becomes myApp.com/search which is problematic for me!
Please note I have two have both the method and the nuxt-link. How can I fix it so when I use the method and go to search page I keep the parameters?
You should use this, as mentioned in the documentation
<nuxt-link :to="{ path: 'search-page', query: { search: number } }">
Try search page
</nuxt-link>
You can also use it this way, depending on what you're trying to achieve.
<button #click="$router.push({ path: 'search-page', query: { search: number } })">
Try some other way
</button>
A correct /pages/search-page.vue page can be found here.
In my Vue app, I can click a link generated by <router-link>...</router-link> and visit a page like: /site/books/00666.html.
The routing config for this is:
{
path: '/books/:id.html',
name: 'BookDetail',
component: BookDetail,
props: true,
}
So I changed the URI in the browser (Fx57) to: /site/books/00777.html to try to display the detail information of another book. It failed with this:
Cannot get /books/00777.html
and the debugger told me something like:
Content security policy is preventing from accessing a resource from 'self'`.
I searched on CSP but can't figure out how to make this working.
Update: To reproduce the issue, I use vue init webpack test and scafolded a blank Vue app with router support.
One new router is added:
{
path: '/book/:id.html',
name: 'BookDetail',
component: BookDetail,
props: true,
}
In the default HelloWorld.vue, just add a few lines with <router-link>:
<ul>
<li><router-link :to="{name: 'BookDetail', params: {id: 12345} }">Book 1</router-link></li>
<li><router-link :to="{name: 'BookDetail', params: {id: 23456} }">Book 2</router-link></li>
</ul>
In the HelloWorld page, clicking the link above will take you to "localhost:8080/book/12345.html". Good.
Change the URI to "localhost:8080/book/23456.html". The browser prompts the same error as before.
Update 2: per hint below, I modified the URI pattern to '/books/:id' and it is working.
Further question: What shall I do if I want to add the .html suffix?
Is it possible for a route-href generated link to have the replace=true option when pushState is enabled?
I have tried:
<a route-href="route: user/details; options.bind: {replace: true}">Link</a>
and it does not work. There is no error and the view changes but after clicking the link a new item in the browser history appears (and it should not).
I don't believe so. The route-href generates an href attribute containing the url to the specified route. To navigate to a route using replace: true you'd have to create a method in your view-model and call this method using a click event. Something like this:
ViewModel
goToRoute() {
this.route.navigateToRoute('myRoute', { id:'someId' }, { replace: true });
}
View
<a click.delegate="goToRoute()"></a>
I'm having a bunch of problems getting jQuery's .on to work with my Rails ajax link.
Specifically, I've got this link:
<div id="item_7_tools" class="item_tools">
<a rel="nofollow" id="book_item_7" data-remote="true" data-method="post" class="book_link" href="bookings">Book this item</a>
</div>
I've trimmed some of the text in the HTML, but suffice to say that that, and my controller response work.
I click "Book this item", it goes off to the controller, the controller does its magic, and sends back my partial that replaces the contents of that div.
So I'm now trying to replace the contents with an ajax spinner while the loading is working, and that's where its going pear-shape.
I'm trying this initial bunch of jQuery code just to make sure I've got my javascript working:
$('div.item_tools')
.on('click', 'a', function() {
console.log("clicky click")
})
.on('ajax:beforeSend', "a", function() {
console.log('the a in div.item_tools is sending its ajax command');
})
.on('ajax:complete', "a", function() {
console.log('ajax request completed');
})
My understanding of that, is that when I then click any link (a) that lives within an element with the item_tools class, it will bubble up to this function, and then log the message into the console. Similarly, a link that has triggered an ajax request will get the same treatment...
(And assuming I can get that to work, then I'll go to work doing the ajax loader spinner).
The behaviour I'm seeing instead, is that when I click the link, there are no messages appearing in my console (trying this on both firefox and chrome), and my ajax link goes off and does its stuff correctly. Just completely ignoring the javascript...
Is this because my clicking the ajax link somehow has blocked the click event from bubbling up? I know that there's a way to do that, but I don't think I've done it anywhere knowingly. Unless OOTB rails/ujs does that?
So my questions:
Is there a way to tell what has had a binding attached to it?
What am I doing wrong with my javascript?
Thanks!
I use this all the time... and it seems to work fine.
Have you tried adding one that's .on('ajax:success')?
Besides that try putting the . for each line on the previous line...? It's possible that it gets to $('div.item_tools') and then auto-inserts a semi-colon as per javascript's standard... Although if that were the case I'd expect it to give you a JS error about the . on the next line. In any case try changing it to:
$('div.item_tools').
on('click', 'a', function() {
console.log("clicky click")
}).
on('ajax:beforeSend', "a", function() {
console.log('the a in div.item_tools is sending its ajax command');
}).
on('ajax:complete', "a", function() {
console.log('ajax request completed');
})
If worse comes to worse try just doing:
$("a").on("ajax:success", function(){
console.log('ajax:success done');
})
And see if it works without the event delegation...
Then change it to this:
$(document).on("ajax:success", "a", function(){
console.log("ajax:success with delegation to document");
})
And see if delegation works all the way up to document instead of just your item_tools
Are you sure that you've named everything right? it's div.item_tools a in your markup?
Turns out that the javascript was being triggered before the DOM had loaded, which meant that stuff weren't being bound...
$(function () {
$('div.item_tools')
.on('click', 'a', function itemToolsAjaxy() {
console.log("clicky click");
})
.on('ajax:beforeSend', "a", function() {
console.log('the a in div.item_tools is sending its ajax command');
$(this).closest('div').html('<img src=/assets/ajax-loader.gif>');
})
});
Added the $(function()) right at the beginning and it delayed the binding until after the DOM had loaded, and then it started working.
Figured this out by using the Chrome developer tools to stick a break on the div.item_tools selector and watched as the browser hit that even before the DOM had been loaded. /facepalm
(I removed the .on('ajax:complete') callback, because it turns out that there's a known limitation where the original trigger element no longer exists because it had been replaced, so there's nothing to perform the callback on. Not relevant to my original problem, but I thought I'd mention it.)
As far as i'm aware, you can either do ajax stuff 2 ways:
By using :remote => true
By using jQuery's $.ajax (or $.post).
With number 2, make sure to change your href='#'
My suggeston is to remove the :remote => true and manually make a jQuery ajax call. That way you can use beforeSend, complete, etc.
If i'm way off track here, someone please help clarify things for me as well.
I am having trouble setting up a simple website with different webpages and staying DRY.
I have everything set up so I the last fragment of the url is the name of the template that needs to be loaded in the content part of the webpage. All I want to do now is load that template in a specific location based on the url.
In any examples, they do this:
{{#if showCreateDialog}}
{{> createDialog}}
{{/if}}
{{#if showInviteDialog}}
{{> inviteDialog}}
{{/if}}
I'd like to do something along the lines of
{{> {{template_name}} }}
Sadly, that doesnt work. I tried this as well:
{{{content}}}
Template.content.content = function () {
var url_frag = Session.get("url_frag");
return Template[url_frag]();
}
This didnt work either. Please help!
Edit:
hmm. perhaps, my error is not in loading the template but in capturing the url:
var TodosRouter = Backbone.Router.extend({
routes: {
"*url": "main"
},
main: function (url) {
Session.set("url", url.split('/'))
}
});
The error I am getting arises when url_frag is undefined...
var url_frag = Session.get("url_frag");
initially, this works, but upon changing webpages, it fails...
Solved. I just left backbone out of it
Template.content.content = function () {
var url = window.location.pathname.split('/');
var url_frag = url.pop()
return Template[url_frag]();
Then in the html:
<template name="content">
{{{content}}}
</template>
You could also try the router smart package at atmosphere, which also supports complex routes and filters.
https://atmosphere.meteor.com/package/router
Install meteorite using npm install -g meteorite
Install router using mrt add router
Add {{renderPage}} to body
Tada! /login now renders {{> login}}
Read the document here: https://github.com/tmeasday/meteor-router