Variable is not defined (sending from HTML to JS file) - javascript

I'm trying to send a variable (user.id - current user's id) into my JQuery file which calls a view to delete some data in a database. The problem is that I don't know how to pass user.id into the JS file to be able to append it to url request.
In my template:
<script src="{% static "js/checkTestsSittings.js" %}">var userid = {{ user.id | safe }};</script>
JS file:
$(document).ready(function () {
alert(userid); // just a test
request_url = '/check-sittings/'+userid+'/';
$.ajax({
url: request_url
})
});
This is what I see in the console:
I'm beginner in JS and Django. Could you give me a hint?

You can't add file and code in a single script tag, you should add them independently, like this
<script>var userid = {{ user.id | safe }};</script>
<script src="{% static "js/checkTestsSittings.js" %}"></script>

Related

Is there any way I can access Django template variables and URL tags in a JS file so that the user can not inspect the data and links?

I want to access Django template variables and URL tags from my javascript file. currently, I'm doing it like follows-
<script>
const addcommentlink = "{% url 'post:add_comment'%}";
const postid = '{{post.id}}';
const deletecommentlink = "{% url 'post:delete_comment' %}";
const editlikelink = "{% url 'post:edit_like' %}";
const profilelink = "{% url 'instagram:profile' 'name' %}";
</script>
<script src="{% static 'post/js/post_details.js' %}"></script>
but I want to access it directly from the post_details.js file. Is there any way to do that?
You can't use Django template language in javascript files.
You can use variables, tags, filters only in a django template.
A template is a text file. It can generate any text-based format (HTML, XML, CSV, etc.).
If you want to access the result of {% url 'name' %} in a javascript file, you must first render it in the template(maybe store it as a data attribute).
A rough example:
<div id="comment" data-add-link="{% url 'post:add_comment'%}" data-delete-link="{% url 'post:delete_comment' %}"></div>
in your post_details.js:
const addcommentlink = $('#comment').data('add-link');
const deletecommentlink = $('#comment').data('delete-link');
However the user will be able to inspect the data links. And if you need anything in the template, then you must assume that it will be visible to the other users.

How to access env veriables in js file in laravel

I intigrate Stripe Api for testing how can i set public key in env.
How to use in strip public key in js
Public key:
STRIPE_KEY=pk_test_IS796OfBm2ZFLfvBbwsXHJLK00fE6oqivk
and js file where use this veriable:
var stripe = Stripe({{ env('STRIPE_KEY') }});
{{ }} is a .blade syntax control, and cannot be used in .js files.
If you have a <script> element inside a .blade.php file, then it will work, but otherwise you'll need to load the file into JS before including the .js file, or get the value via an ajax call.
For example, loading the variable to js before including the .js script:
example.blade.php:
<script type="text/javascript">
let stripe_key = '{{ env("STRIPE_KEY") }}';
</script>
<script src="{{ asset('js/stripe.js') }}"></script>

Making a django html template request with multiple key values

I'm new to using Django or even creating a website, so please bear with me if I have provided too little/much detail about the issue I'm facing. Also, I've spent the better part of the last week trolling SO pages, blogs, Django tutorials, Django documentation, etc. trying to solve the issue myself. Maybe I've overlooked something or I'm just unlucky, but nothing I've found addresses my particular situation in its entirety. Most examples seem to focus on handling requests in views.py and not on how the original request is made in the Django template.
I have a Django template, view_table.html, that displays a Bootstrap DataTable table object to a user. The second column of this table is a BigIntegerField called MyRow_ID. I currently have code in MyCode.js that allows the user to highlight multiple rows, and when button modify_button is clicked, the MyRow_ID values for the selected rows (e.g. [2, 13, 14]) are captured into a JS dict called sent_data. After these values have been captured, I'd like for modify_button to create a GET request that sends sent_data along with it. After matching in urls.py and calling the modify_data function in views.py, modify_data should render a new page modify_table.html while passing back the model instances matching MyRow_ID in order to display only the selected rows' data. I think I'm really close, and perhaps only a tweak to the regex expression is what I need, but here are my questions:
How do I create a GET request in the Django template view_table.html that passes sent_data along to Django? Currently I'm using a form with the method and action attributes set to "GET" and "{% url 'modify_data' sent_data=sent_data %}" respectively. I'm assuming GET and not POST should be used because the request isn't modifying the backend, it's more of a "filter the view" type of request. Is this a correct assumption? What would the requested url look like? Say MyRow_ID values are [2,13,14]. Would the get request look something like /modify_data/matched_row_1=2&matched_row_2=13&matched_row_3=14? Do I have to create this url string myself in the template by iterating over sent_data and attaching a "matched_row_n=" string, or is there a simpler way for the template to create this automatically in the request?
What's the correct regex pattern that should be used in myapp/urls.py, given sent_data could have anywhere from 1 to n unique MyRow_ID values, assuming 1 to n rows are selected respectively? (Obviously robust code would include handling where 0 rows are selected and modify_button is clicked, but let's set that aside for now.) Currently I'm getting a NoReverseMatch Error at /myapp/view_data/: Reverse for 'modify_data' with arguments '()' and keyword arguments '{u'sent_data': ''}' not found. I'm new to using regex, and I know what I have in myapp/urls.py is wrong.
Is the code in myapp/views.py correct to filter the matching model instances and render modify_table.html with the selected rows?
view_table.html:
<!DOCTYPE html>
<html>
<head>
## Bunch of code… ##
</head>
<body>
<div class="col col-xs-12 text-right">
<form style="display" method="get" action="{% url 'modify_data' sent_data=sent_data %}">
<button id="modify_button" type="button" class="btn btn-primary btn-create">Modify Data</button>
</form>
</div>
<br><br><br>
<table id="my_table">
## Code that displays my_table ##
</table>
<!-- Execute JS scripts -->
<script type="text/javascript" src="{% static "myapp/js/jquery-1.12.0.min.js" %}"></script>
<script type="text/javascript" src="{% static "myapp/js/jquery.dataTables.min.js" %}"></script>
<script type="text/javascript" src="{% static "myapp/js/bootstrap.min.js" %}"></script>
<script type="text/javascript" src="{% static "myapp/js/dataTables.bootstrap.min.js" %}"></script>
<script type="text/javascript">
var sent_data = [];
</script>
<script type="text/javascript" src="{% static "myapp/js/MyCode.js" %}"></script>
</body>
</html>
MyCode.js:
$(document).ready(function(){
var oTable = $('#my_table').DataTable();
var selected_data = [];
$('#my_table tbody').on('click','tr',function(){
$(this).toggleClass('active');
});
$('#modify_button').click(function(event){
selected_data = $.map(oTable.rows('.active').data(), function (item) {
return item[1]
});
sent_data = { 'modify_rows': selected_data };
});
});
I should note that I'm using MyRow_ID and not the native DataTable attribute rowID because I'm assuming DataTable's automatically-created rowID do not match the automatically-created primary keys (pk) that Django is using. Is this a correct assumption?
myapp/urls.py:
from django.conf.urls import url
from . import views
from .models import MyDataModel
urlpatterns = [
url(r'^view_data/$', views.view_data, name='view_data'),
url(r'^modify_data/(?P<sent_data>\d+)/$', views.modify_data, name='modify_data'),
]
myapp/views.py:
from django.forms import modelformset_factory
from django.shortcuts import render
from django.http import HttpResponse
from .models import MyDataModel
def view_data(request):
myData = MyDataModel.objects.all()
return render(request, 'myapp/view_table.html', {'myData': myData})
def modify_data(request, sent_data):
MyDataFormSet = modelformset_factory(MyDataModel, fields=('MyRow_ID','MyRow_Text'))
if request.method == 'GET':
selected_rows = sent_data['modify_rows']
## selected_rows = request.GET['modify_rows']
formset = MyDataFormSet(queryset=MyDataModel.objects.filter(MyRow_ID__in=selected_rows))
selected_data = MyDataModel.objects.filter(MyRow_ID__in=selected_rows)
return render(request, 'myapp/modify_data.html', {'formset': formset, 'selected_data': selected_data})
else:
return HttpResponse('A GET request was not received.')
Finally, modify_data.html:
<!DOCTYPE html>
<html>
<head>
## Bunch of code… ##
</head>
<body>
<div class="col col-xs-12 text-right">
<form method="post" action="">
{% csrf_token %}
{{ formset }}
<button id="submit_changes" type="button" class="btn btn-primary btn-create">Submit Changes</button>
</form>
</div>
<br><br><br>
<table id="selected_rows_table">
## Code that displays selected rows passed as selected_data ##
</table>
</body>
</html>
Any help is much appreciated, thank you in advance!
Through much trial and error and good old-fashioned googling I was able to work out the above issues and gain a better understanding of query strings, regex patterns and even how to use an AJAX request to accomplish my original goal.
My original goal had been to allow the user to select multiple rows of data, click a button, and then edit them simultaneously in a form, said form either being rendered on a new page or in a modal. The following posts/blogs were very helpful for each piece of the puzzle:
Django documentation on urls, request/responses and model formsets:
https://docs.djangoproject.com/en/1.10/topics/http/urls/
https://docs.djangoproject.com/en/1.10/ref/request-response/
https://docs.djangoproject.com/en/1.10/topics/forms/modelforms/#model-formsets
Guide to creating Bootstrap modals:
https://coolestguidesontheplanet.com/bootstrap/modal.php
Understanding of how urls and query strings work with multiple values for a single key:
http://meyerweb.com/eric/tools/dencoder/ (for testing)
How to pass multiple values for a single URL parameter?
Capturing url parameters in request.GET
Example of using Django AJAX Form:
http://schinckel.net/2013/06/13/django-ajax-forms/
Code for handling response from server of an AJAX request, and refreshing the page:
Update div with jQuery ajax response html
One important thing to note about using a query string with multiple values for a single key, e.g. say the url of my GET request is something like www.myurl.com/?page=1&page=2&page=3; when using an AJAX GET request, it will create a query string for this url with www.myurl.com/?page[]=1&page[]=2&page[]=3, i.e. it adds the "[]" brackets for any key with multiple values. The usual answers (as documented by Django and others) to retrieve all values of the "page" key in views.py when processing the request is to use request.GET.getlist('page'). THIS WILL NOT WORK. You need to use request.GET.getlist('page[]'). Add the brackets in request.method.getlist() or remove them from the original query string in the url requested.
Finally, here are some snippets of modified code that addressed my original questions:
In view_data.html, updated form:
<form id="modify_form" method="post" action="{% url 'modify_data' %}">
{% csrf_token %}
{{ formset }}
</form>
In myapp/urls.py, fixed url finder to handle any query string passed:
url(r'^modify_data/$', views.modify_data, name='modify_data'),
In myapp/views.py, change modify_data code:
def modify_data(request):
MyDataFormSet = modelformset_factory(MyDataModel, fields=('MyRow_ID','MyRow_Text'))
if request.is_ajax():
template = 'myapp/view_data.html'
else:
template = 'myapp/modify_data.html'
if request.method == 'GET':
selected_rows = request.GET.getlist['modify_rows[]']
formset = MyDataFormSet(queryset=MyDataModel.objects.filter(MyRow_ID__in=selected_rows))
selected_data = MyDataModel.objects.filter(MyRow_ID__in=selected_rows)
return render(request, template, {'formset': formset, 'selected_data': selected_data})
else:
return HttpResponse('A GET request was not received.')
In MyCode.js, code has been updated to reflect using modal form, AJAX GET request and refreshing the DOM with Django view.py's response:
$("#modify_button").click(function(){
selected_data = $.map(oTable.rows('.active').data(), function (item) {
return item[1]
});
$.ajax({
// The URL for the request
url: URL,
// The data to send (will be converted to a query string)
data: {
modify_rows: selected_data,
},
// Whether this is a POST or GET request
type: "GET",
})
// Code to run if the request succeeds (is done);
// The response is passed to the function
.done(function( json ) {
var forms_result = $('<div />').append(json).find('#modify_form').html();
$('#modify_form').html(forms_result);
var table_result = $('<div />').append(json).find('#my_table').html();
$('#my_table').html(table_result);
})
// Code to run if the request fails; the raw request
// and status codes are passed to the function
.fail(function( xhr, status, errorThrown ) {
alert( "Sorry, there was a problem!" );
console.log( "Error: " + errorThrown );
console.log( "Status: " + status );
console.dir( xhr );
})
});
Hope all of this is somewhat helpful to someone else, if not, this whole process has been a great learning experience for me!

How to store contents of file opened by Django in Javascript

I'm trying to figure out the simplest way to access my file in my HTML template in Django and store this file as a string in Javascript. I've tried directly storing it via:
var global_data = '{{ accessed_file }}';
But for me that did not work. I was able to access it by loading my static files directly in the HTML document and then retrieving it with $.get.
$(document).ready(function() {
{% with '/path/to/file.txt' as accessed_file %}
$.get("{% static accessed_pdb %}", function(data){
// function using data
});
});
{% endwith %}
However, I want to be able to have access to data outside of the $.get. I've tried assigning it to a global variable, but with no luck.
$(document).ready(function() {
var global_data = '';
{% with '/path/to/file.txt' as accessed_file %}
$.get("{% static accessed_pdb %}", function(data){
global_data = data;
});
//access global_data outside of $.get
});
{% endwith %}
I'm using the file for a visual on my site and currently I am unable to manipulate it using HTML buttons when it is within the $.get without reloading the file again. I'm not quite sure how else to approach the problem, so any feeback would be appreciated.
Set the value to a hidden element
<input type="hidden" value="{{ accessed_file }}" id="file">
And access it via:
$('#file').val()
You cannot access the global data outside of the $.get because the result is returned to the callback function asynchronously, it will run after your code outside of $.get runs. You can use promises (https://api.jquery.com/category/deferred-object/) to wait for the data.

Laravel 5 External JavaScript Files_ JavaScript stack

the following JavaScript is working perfect in side the test.blad.php file
but when i made external test.js file at the browser i get some thing like
http://localhost:8000/%7B%7Burl('/barcode')%7D%7D?j_barcode=112234
instead of
http://localhost:8000/barcode?j_barcode=112234
the code in test.js file is :
$(document).ready(function(){
$('#barcode').keyup(function(event){
if(event.keyCode == 13){
var j_barcode = $('#barcode').val();
$.get("{{url('/barcode')}}", {j_barcode:j_barcode}, function(data) {
console.log(data) ;
//success data
$.each(data,function(i, obj){
document.getElementById("item").value =obj.itemName;
document.getElementById("itemId").value = obj.id;
console.log(data) ;
});
});
}
});
});
and the route.php
Route::get('/barcode' , 'testController#getBarcode');
at last i decleared the test.js in test.blade.php as
<script type="text/javascript" src="/hsm/js/test.js" ></script>
You can not use blade or php code inside files which are not interpreted by php.
The simplest way, as already suggested by #dev-null is to hardcode that url. But that generates problems when you're on a sub page like "/articles/2015" since it will then try to call "/articles/barcode".
You will have to find a way to pass the site root url to your js file.
The way I always solve this is to define a global variable in my main template with all the php interpreted values required in js.
var App = {
root: '{{ url('/barcode') }}',
texts: {
// some translated texts for js
}
};
That way you can easily access it in all your js files:
$.get(App.root + '/barcode')...
Note: If you use named routes like me you will have to add each URL separately instead of just the root.
After some research, this is my solution:
Step 1. In the blade file, add a yielded section, immediately (just to keep your scripts neat) before referring to external .js file, do something like following,
#section('js_after')
<script>let dataUrl = "{{ route('subcat') }}"</script>
<!--Then external javascript file -->
<script src="{{ asset('js/pages/somescript.js ') }}"></script>
#endsection
Step 2. In your somescript.js file, you may refer and manipulate with this pre-defined variable dataUrl, such as,
var url = dataUrl+'?someParam='+id
$.get(url)
reference: https://stackoverflow.com/a/59994382/3107052

Categories

Resources