Call django urls inside javascript on click event - javascript

I got a javascript onclick event inside a template, and I want to call one of my Django urls with an id parameter from it, like this :
$(document).on('click', '.alink', function () {
var id = $(this).attr('id');
document.location.href ="{% url 'myapp:productdetailorder' id %}"
});
Course this is not working at all. Any idea ?
Thanks in advance !!

I think the best way to do this is to create a html data-* attribute with the URL rendered in a template and then use javascript to retrieve that.
This way you avoid mixing js/django template stuff together. Also, I keep all of my JS in a separate file outside the view (which is a much better practice in general), and therefore trying to mix these two won't work.
For instance, if you have a url you want, just create an html hidden element:
<input type="hidden" id="Url" data-url="{% url 'myapp:productdetail' id %}" />
Then, in your JS:
$(document).on('click', '.alink', function () {
var url = $("#Url").attr("data-url");
});
I frequently use this pattern for dropdown lists so that I don't have to serve all of the options when I first render the page (and this usually speeds it up).

You are trying to access javascript variable that is created at user click on frontend within your Django template at the backend. But, you already know that it would not work.
A better option would be to reconstruct the url in javascript:
$(document).on('click', '.alink', function () {
// Generate URL without "id" bit
var url = "{% url 'myapp:productdetail' %}";
var id = $(this).attr('id');
// Construct the full URL with "id"
document.location.href = url + "/" + id;
});
If you don't have a django url helper that would return a URL that you need, you can print out just any and simply replace it in javascript like so:
$(document).on('click', '.alink', function () {
var url = "{% url 'myapp:productdetail' 123 %}";
var id = $(this).attr('id');
// Construct the full URL with "id"
document.location.href = url.replace('123', id);
});

The problem seems to be in that you using django template language in js static file(am i right?)
Try to move that variable to html template file, ex:
<script type=text/javascript>
var a = "{% url'myapp:productdetail' id %}" </script>
And in static js file:
document.location.href = a;

You can use javascript code " window.location.origin " , this will give base url and after that you can add "/pathname"

You don't need to pass any of that...
Write.
location.href = "/" + id
That's all.

Related

jQuery: simplest way to check URL for a parameter and pass it to anchor href if it exists

https://example.com/index.php contains the following two anchor tags:
Link 1
Link 2
One or more parameters may be passed in the URL, eg. https://example.com/index.php?a=1&b=2
Using jQuery/Javascript, what is the simplest way to test for the presence of parameter a in the URL and append it to the hrefs in the above links if it exists, so they become:
Link 1
Link 2
You are getting the logic of app design wrong. That is something you should do on the back-end of the web application; you check for the input parameters in the GET request and format the links hyper-reference accordingly.Also if you are going to be passing the value many times it may be easier for you to store it in the user session temporary environment (using cookies).
If you are using PHP (as I may guess by the file's extension) you can do that very easily:
<a href="page1.php<?
if(array_key_exists('your_key', $_GET) {
echo('?your_key=' . $_GET['your_key'])
}
?>" class="hyperlink">Link 1</a>
<a href="page2.php?<?
if(array_key_exists('your_key', $_GET) {
echo('your_key=' . $_GET['your_key'] . '&')
}
?>b=1" class="hyperlink">Link 2</a>
Client side the simplest is use the URL API
var mainUrl = new URL(location.href);
// Won't work in this demo so hard code href
mainUrl = new URL('http://example.com?a=foo&b=2');
var paramA = mainUrl.searchParams.get('a');
$('a.hyperlink').prop('href', function(){
var url = new URL(this.href);
url.searchParams.set('a', paramA);
return url;
})
// set query params as text just for demo
.text(function(){
return 'Query Params: ' + this.search;
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Link 1<br/>
Link 2
You can try using regex, by the way as i can see you are using php so filter them with $_REQUEST
otherwise getting everything after the link in regex
var url = window.location.href
var res = url.match("/\?(.*)/i")
res should contain everything from ?getTO&otherget

Sending JavaScript object to other page

When I click on button on my webpage it should redirect me to other page with JavaScript object. I am not able to code for sending java script object with onclick event to other page. Help me in code for sender side page and receiver side page.
Java script object contains array of multiple key value pairs, and I want to send this array to other page.
Example:
data= { {region: "Maharashtra",sector: "Manufacturing",size: "MSME",year: "2008"} and many }
I apologize if my question is not clear.
There are some ways to do this on JS:
Using Cookies
Using QueryString
Using LocalStorage
Note :
Action using above technique only affected on client side only. Except, targeted page sending it into server.
you don't need java script, enough add params to your <a src=""></a>
for example in html:
<a src="www.something.com/something?region=Maharasta&size=MSME"> Link </a>
or you can add params to your url dynamic for example by jQuery:
var params = { fuu:1680, buu:1050 };
var str = '?' + jQuery.param( params );
$( "#myLink" ).attr('src', $('#myLink").attr('src') + str)

How to access URL parameters sent to div via jQuery load()

I am using jQuery load() to load a partial page into a div. I want to pass url parameters to the partial page like so
<div id='partial'></div>
<script>
$('#partial').load('child_page.html?key=1');
</script>
How do I access these parameters from inside the child page? I tried the following in the child page, but the issue is that the window.location is not giving me child_page.html?key=1 but is giving me the root page url.
<script>
var url = window.location;
//code to parse the url to extract the parameters goes here
</script>
It is not possible for the "child page" to have its own DOM and scripting context, because it was simply retrieved as a string (via AJAX) and inserted into the parent page. Therefore it does not have its own window.location. Everything is added to the DOM of the parent page, and scripts are executed in the context of the parent page.
If you want to share variables between your parent page and the new script loaded with load, you can attach the variable to window and then access it in the script of the "child page".
For example:
// parent page
window.sharedVariable = "Hello World!";
$('#partial').load(url);
// child page
var v = window.sharedVariable;
Working demo (child page)
Update:
Here is an alternate method to support multiple partials, using data attributes to share the variables.
// parent page
$('#partial_1').load(url).data("param", "111");
$('#partial_2').load(url).data("param", "222");
$('#partial_3').load(url).data("param", "333");
// child page
var scriptTag = document.scripts[document.scripts.length - 1];
var parentTag = scriptTag.parentNode;
var param = $(parentTag).data("param");
Basically, we set the data we want to share in the partial's div. And then in the "child page", we find the current running script tag, then the parent tag would be the div that has the data in it.
Working demo (child page)
This takes a slightly different course, but achieves the result you're looking for just as well. You can use the HTML5 History API and do something like this:
history.replaceState(null, null, '?key=1');
var test = $('#partial').load('two.html');
Then from two.html, the window.location.search call will give you ?key=1 and you can parse the query string from there..
How to access URL parameters sent to div via jQuery load()
Edit, Updated
Note, original Question does not appear to include description of script element expected , to run, within returned html from call to .load()
Try utilizing beforeSend to set settings url at jqxhr object , access jqxhr object within .load() complete callback
var url = "https://gist.githubusercontent.com/anonymous/4e9213856be834b88f90/raw/1d90ab5df79e6ee081db2ff8b94806ef27cbd422/abc.html";
$.ajaxSetup({
beforeSend: function(jqxhr, settings) {
jqxhr.params = settings.url
}
});
function loadComplete(data, textStatus, jqxhr) {
$(this).find("h1")
.html(function(_, html) {
return html + " My param is " + jqxhr.params.split("?")[1]
});
};
$("#partial_1").load(url + "?111", loadComplete);
$("#partial_2").load(url + "?222", loadComplete);
$("#partial_3").load(url).load(url + "?333", loadComplete);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div id="partial_1"></div>
<div id="partial_2"></div>
<div id="partial_3"></div>
jsfiddle http://jsfiddle.net/L9kumjmo/5/

Create link in handlebars.js using helper

I have tried to follow the example in the handlebars documentation on how to create a link, but the instructions are very unclear to me. handlebarsjs.com/expressions.html (see "Helpers")
First of all, without the link helper I can make the link text appear on the screen, but just as text, not a link.
<script id="template" type="text/x-handlebars-template">
<h4>{{{my_link}}}</h4>
</script>
And the text is retrieved from an ajax request.
Then I add the link keyword
<h4>{{{link my_link}}}</h4>
And then nothing is displayed. This is the helper code I have currently, which doesn't work:
$(function(){
Handlebars.registerHelper('link', function(my_link) {
var url = Handlebars.escapeExpression(my_link.url);
var result = "<a href='" + url + "'></a>";
console.log(result);
return new Handlebars.SafeString(result);
});
});
Is it relevant where I put this piece of code in the javascript?
When I click a submit button, the ajax request is made and the link is retrieved. With the link helper, the console.log gives an empty link:
"<a href=''></a>"
Since you registered the name of the helper as link, your template should start with {{{link
So
<h4>{{{my_link}}}</h4>
should be
<h4>{{{link my_link}}}</h4>
And
var url = Handlebars.escapeExpression(my_link.url);
should be changed to
var url = Handlebars.escapeExpression(my_link);
Instead of creating the whole a element I can suggest you to create helper for attribute only. This way you can reuse it to many others elements and also the code will be much simpler and better to read in the templates. For example I have build this attr helper function:
handlebars.registerHelper('attr', function(name, data) {
if(typeof target === 'undefined') target = "";
var result = ' ' + name + '="' + data + '" ';
return new handlebars.SafeString(result);
});
And here is how it looks in the template:
<a target="_blank" {{attr 'href' general.link}}><img src="assets/images/nice_image.png" class="link-icon" /></a>
I think this approach is much more simpler, and even more reusable than having helper to create the whole element. You can name the helper in the way that will match the attribute also, href, src...

Calling Django `reverse` in client-side Javascript

I'm using Django on Appengine. I'm using the django reverse() function everywhere, keeping everything as DRY as possible.
However, I'm having trouble applying this to my client-side javascript. There is a JS class that loads some data depending on a passed-in ID. Is there a standard way to not-hardcode the URL that this data should come from?
var rq = new Request.HTML({
'update':this.element,
}).get('/template/'+template_id+'/preview'); //The part that bothers me.
There is another method, which doesn't require exposing the entire url structure or ajax requests for resolving each url. While it's not really beautiful, it beats the others with simplicity:
var url = '{% url blog_view_post 999 %}'.replace (999, post_id);
(blog_view_post urls must not contain the magic 999 number themselves of course.)
Having just struggled with this, I came up with a slightly different solution.
In my case, I wanted an external JS script to invoke an AJAX call on a button click (after doing some other processing).
In the HTML, I used an HTML-5 custom attribute thus
<button ... id="test-button" data-ajax-target="{% url 'named-url' %}">
Then, in the javascript, simply did
$.post($("#test-button").attr("data-ajax-target"), ... );
Which meant Django's template system did all the reverse() logic for me.
The most reasonable solution seems to be passing a list of URLs in a JavaScript file, and having a JavaScript equivalent of reverse() available on the client. The only objection might be that the entire URL structure is exposed.
Here is such a function (from this question).
Good thing is to assume that all parameters from JavaScript to Django will be passed as request.GET or request.POST. You can do that in most cases, because you don't need nice formatted urls for JavaScript queries.
Then only problem is to pass url from Django to JavaScript. I have published library for that. Example code:
urls.py
def javascript_settings():
return {
'template_preview_url': reverse('template-preview'),
}
javascript
$.ajax({
type: 'POST',
url: configuration['my_rendering_app']['template_preview_url'],
data: { template: 'foo.html' },
});
Similar to Anatoly's answer, but a little more flexible. Put at the top of the page:
<script type="text/javascript">
window.myviewURL = '{% url myview foobar %}';
</script>
Then you can do something like
url = window.myviewURL.replace('foobar','my_id');
or whatever. If your url contains multiple variables just run the replace method multiple times.
I like Anatoly's idea, but I think using a specific integer is dangerous. I typically want to specify an say an object id, which are always required to be positive, so I just use negative integers as placeholders. This means adding -? to the the url definition, like so:
url(r'^events/(?P<event_id>-?\d+)/$', events.views.event_details),
Then I can get the reverse url in a template by writing
{% url 'events.views.event_details' event_id=-1 %}
And use replace in javascript to replace the placeholder -1, so that in the template I would write something like
<script type="text/javascript">
var actual_event_id = 123;
var url = "{% url 'events.views.event_details' event_id=-1 %}".replace('-1', actual_event_id);
</script>
This easily extends to multiple arguments too, and the mapping for a particular argument is visible directly in the template.
I've found a simple trick for this. If your url is a pattern like:
"xyz/(?P<stuff>.*)$"
and you want to reverse in the JS without actually providing stuff (deferring to the JS run time to provide this) - you can do the following:
Alter the view to give the parameter a default value - of none, and handle that by responding with an error if its not set:
views.py
def xzy(stuff=None):
if not stuff:
raise Http404
... < rest of the view code> ...
Alter the URL match to make the parameter optional: "xyz/(?P<stuff>.*)?$"
And in the template js code:
.ajax({
url: "{{ url views.xyz }}" + js_stuff,
... ...
})
The generated template should then have the URL without the parameter in the JS, and in the JS you can simply concatenate on the parameter(s).
Use this package: https://github.com/ierror/django-js-reverse
You'll have an object in your JS with all the urls defined in django. It's the best approach I found so far.
The only thing you need to do is add the generated js in the head of your base template and run a management command to update the generated js everytime you add a url
One of the solutions I came with is to generate urls on backend and pass them to browser somehow.
It may not be suitable in every case, but I have a table (populated with AJAX) and clicking on a row should take the user to the single entry from this table.
(I am using django-restframework and Datatables).
Each entry from AJAX has the url attached:
class MyObjectSerializer(serializers.ModelSerializer):
url = SerializerMethodField()
# other elements
def get_url(self, obj):
return reverse("get_my_object", args=(obj.id,))
on loading ajax each url is attached as data attribute to row:
var table = $('#my-table').DataTable({
createdRow: function ( row, data, index ) {
$(row).data("url", data["url"])
}
});
and on click we use this data attribute for url:
table.on( 'click', 'tbody tr', function () {
window.location.href = $(this).data("url");
} );
I always use strings as opposed to integers in configuring urls, i.e.
instead of something like
... r'^something/(?P<first_integer_parameter>\d+)/something_else/(?P<second_integer_parameter>\d+)/' ...
e.g: something/911/something_else/8/
I would replace 'd' for integers with 'w' for strings like so ...
... r'^something/(?P<first_integer_parameter>\w+)/something_else/(?P<second_integer_parameter>\w+)/' ...
Then, in javascript I can put strings as placeholders and the django template engine will not complain either:
...
var url = `{% url 'myapiname:urlname' 'xxz' 'xxy' %}?first_kwarg=${first_kwarg_value}&second_kwarg=${second_kwarg_value}`.replace('xxz',first_integer_paramater_value).replace('xxy', second_integer_parameter_value);
var x = new L.GeoJSON.AJAX(url, {
style: function(feature){
...
and the url will remain the same, i.e something/911/something_else/8/.
This way you avoid the integer parameters replacement issue as string placeholders (a,b,c,d,...z) are not expected in as parameters

Categories

Resources