angularjs not responding the GET method - django

i am relatively new in django and angualarJs.The problem is that angularJs is not responding the get method properly.I have a webpage developed by django where i have a search field.For the execution of search i use a angularJs functionality that is ng-submit and write angularJs code to return value using get method.May be i made a mistake here.you can see my code... here is my template which containing the angularJs also...
<div class="navbar navbar-default " ng-controller="NavCtrl">
<form action="" class="navbar-form navbar-right" ng-submit="search()">
<input class="form-control col-lg-8" type="text" placeholder="Search" ng-model="term"></input>
</form>
</div>
<script>
app.controller("NavCtrl", ['$scope', '$http', '$location', '$q', '$timeout',
function NavCtrl($scope, $http, $location, $q, $timeout) {
$scope.results = ["Test"];
$scope.term = "";
$scope.reqs = "5";
$scope.pics = "45";
$scope.ddata = "asdasd";
$scope.ddata = $http.post("{% url 'get-nav-info' %}").success(
function (result) {
//$scope.reqs = result.data.data.num_request;
//$scope.pics = result.data.data.num_photo;
return result.data;
}
);
//$scope.reqs = $scope.ddata.num_request;
//$scope.pics = $scope.ddata.num_photo;
$scope.search = function () {
//alert("test");
//$location.absUrl("{% url 'search-term-show' %}").search({'term':$scope.term}).apply();
//$location.path("{% url 'search-term-show' %}").search({'term':$scope.term}).apply();
$http.get("{% url 'search-term-show' %}?term=" + $scope.term).success(function (result) {
return result.data;
});
//$scope.$apply();
}
}
]);
</script>
now the problem is that while i press enter ,there is no result,but if i manually write this URL which is http://www.kothay.com/searchphoto/?term=a in the address bar then the result is showing .In mention,this url is the that url which should be appear in the address bar when i press the enter to search my photos.But with the enter press its not appearing in the address bar and that's why the results are not showing.I hope you can understand what i am trying to say.May be there is a mistake in my code.Please help me to fix this problem.

You are doing thing wrong.
1st, the success is a defer of get, so return result.data and returns it to the get deferred and there it goes to the heaven. So if you would like to keep the current architecture it should look more like this
$scope.search = [];
getsearch = function () {
$http.get("{% url 'search-term-show' %}?term=" + $scope.term).success(function (result) {
$scope.search = result.data;
});
};
getsearch();
2nd that can still not update your UI cuz if the ctrl function is over and the digest is over before your response it wont update your UI cuz its in another scope (not $scope, but the programmatically term scope). The solution to this is to put your data in a service and in your ctr just do.
function ctrl($scope, myservice){
$scope.data = myservice;
}
ng-repeat="x in data.results"
Here is a full tutorial http://bresleveloper.blogspot.co.il/2013/08/breslevelopers-angularjs-tutorial.html
And last thing its just a good practice to always have .error(...)

Related

NullReferenceException while passing list of object from view to controller

I am trying to save list of object from view to controller but i am getting NullReferenceException when list is more that 25. It works fine if list less than 25.
public async Task<IActionResult> ImportStudentExcel(IFormFile file)
{
var list = new List<StudentImport>();
//Here it contains logic for adding item to list from excel file
ViewBag.FileName = file.FileName;
return View(list.ToList());
}
I am getting all the item in my view
I am doing this to bind properties
//Containes Table for Showing List
<form id="saveForm" asp-action="SaveFromImport" asp-controller="StudentImport" method="POST">
<input type="hidden" name="filename" value="#ViewBag.FileName">
#for(int i=0; i<Model.Count; i++)
{
<input asp-for="#Model[#i].Fullname" type="hidden" value="#Model[#i].Fullname"/>
<input asp-for="#Model[#i].Gender" type="hidden" value="#Model[#i].Gender"/>
<input asp-for="#Model[#i].DOB" type="hidden" value="#Model[#i].DOB"/>
// Other 15 Properties Like Address, PhoneNumber, RegNo etc
}
<input type="submit" value="Save">
</form>
When I inspect this page all item are present
public async Task<IActionResult> SaveFromImport(List<StudentImport> students, string filename)
{
try
{
foreach (var t in students)
{
System.Console.WriteLine(t.Fullname);
//Save to DB
}
}
catch (Exception e)
{
System.Console.WriteLine(e.ToString());
}
return RedirectToAction("Index", "Student");
}
Am getting NullReference at foreach Statement. I dont know whats going on. It works as expected when list count is 13 but wont work when count is 25 or more, It also works when there is only one property in StudentImportModel and count is sttil 25.
The ExceptionMessage in my case was NullReferenceException but the actual error was InvalidDataException: Form value count limit 1024 exceeded.
However, I managed to solve this by adding this code in ConfigureServices method.
services.Configure<FormOptions>(options =>
{
options.ValueCountLimit = 6000;
});

Pass javascript variable to views.py

I really need some help on this subject, which seems easy, but i cant get myself to figure out the problem.
I understand that using ajax is the best way to pass a variable from a template to a view.
Is what i have done good, or would you recommend i try something different ?
function updateArea(e) {
var data = draw.getAll();
var answer = document.getElementById('calculated-area');
if (data.features.length > 0) {
var area = turf.area(data);
// restrict to area to 2 decimal points
var rounded_area = Math.round(area*100)/100;
answer.innerHTML = '<p><strong>' + rounded_area + '</strong></p><p>square meters</p>';
var convertedData = 'text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(data));
document.getElementById('export').setAttribute('href', 'data:' + convertedData);
document.getElementById('export').setAttribute('download','data.geojson');
} else {
answer.innerHTML = '';
if (e.type !== 'draw.delete') alert("Use the draw tools to draw a polygon!");
}
}
I want to take the area variable and convertedData variable and pass them to a view.
So after some searching and trial and error, here is what I tried to do using Ajax.
When I run this i get no errors, but i get nothing in my database.
template.html
<form id="areaform" method="POST">
{% csrf_token %}
<input type="submit" name="area" value=""/>
</form>
$(document).on('submit', '#areaform',function(e) {
e.preventDefault();
$.ajax({
type: 'POST',
url:'fertisatmap/area',
data:{
name: $('#area').val(),
},
sucess:function(){}
});
});
urls.py
path('fertisatmap/area', fertisat_views.fertisatareaview, name='fertisat-area'),
views.py
def fertisatareaview(request):
if request.method == "POST":
area = request.POST['area']
Fertidb.objects.create(
area = area)
return HttpResponse('')

How to mock a ref variable so that we can test conditions based on it?

I have an file input element which is bound to a ref variable. Based on the files uploaded, in the onChange event, the file contents are processed . Currently I am writing unit test cases to test this functionality.
App.js
export class Dashboard extends React.Component {
constructor(props) {
this.uploadFile = React.createRef();
//Constructing...
}
readFileContents() {
const files = this.uploadFile.current.files;
for (let key in files) {
if (files.hasOwnProperty(key)) {
const file = files[key];
const reader = new FileReader();
let settings;
// eslint-disable-next-line no-loop-func
reader.onload = e => {
const extension = file.name.split('.')[1];
//OnLoad Handler
};
console.log(this.uploadFile.current.files)
reader.readAsText(file); //TypeError: Failed to execute 'readAsText' on 'FileReader': parameter 1 is not of type 'Blob'.
}
}
};
render() {
return (
<div className="dashboard wrapper m-padding">
<div className="dashboard-header clearfix">
<input
type="file"
ref={this.uploadFile}
webkitdirectory="true"
mozdirectory="true"
hidden
onChange={this.readFileContents}
onClick={this.reset}
/>
<Button
outline
className="toggle-btn float-right"
onClick={this.openFileDialog}
>
Choose folder
</Button>
</div>
</div>
);
}
}
I started off with this stack overflow answer and was able to mock the FileReader.
I initially thought simulating the change event with the target files as below, will automatically reflect on the values for this.uploadFile .
const file = new Blob([fileContents], {type : 'application/json'});
var event = {"target": {"files": []}};
event.target.files.push(file);
DashboardWrapper.find('input').first().simulate('change', event);
But the behaviour wasnt as I expected and got the below error.
TypeError: Failed to execute 'readAsText' on 'FileReader': parameter 1 is not of type 'Blob'.
Following this I have been trying to change the files key in the ref variable directly from the test file, with no results and the same error.
I would like to first understand if my approach is right. If not, what is the right way to do it?
As far as I can understand, testing the actual file upload is not recommended in a unit test. After all, these inputs should be thoroughly tested already.
That being said, I had a similar requirement and I solved it like so (I am using VueJS and Jest, but the approach should be similar):
Code:
<img v-if="showLogo && currentFile" class="image-preview" :src="currentFile"/>
<input
class="file-input"
type="file"
ref="fileInput"
#change="handleFileUpload()"/>
Test:
it('should render the logo if it got uploaded', async () => {
const wrapper = shallowMount(ApplicationLogoUpload, {
store,
localVue,
propsData: {
showLogo: true
}
});
const fileInput = wrapper.find('.file-input');
const mockedGet = jest.fn();
mockedGet.mockReturnValue(['file1']);
Object.defineProperty(fileInput.element, 'files', {
get: mockedGet
});
fileInput.trigger('change');
const imagePreview = wrapper.find('.image-preview');
expect(imagePreview.attributes().src).toEqual('file1');
});
Most importantly, I mocked the uploaded files using
const mockedGet = jest.fn();
mockedGet.mockReturnValue(['file1']);
Object.defineProperty(fileInput.element, 'files', {
get: mockedGet
});
I trigger the upload by calling fileInput.trigger('change');
Afterwards, the assertion can be done: src being equal to the mocked file.

Django has no response to anchor tag

test
...
<div class="tab-pane " id="test">
<table>
...
</table>
</div>
When #test anchor is clicked, the behavior should be logged in the server. So in urls.py, I defined something like this
url(r'#test$', views.log())
or
url(r'.*#test$', views.log())
But it seems it doesn't work.
I have to use anchor here, because I don't want to refresh the page.
Any ideas?
Here is some JavaScript that takes links with a href attribute starting with # and makes a request to https://localhost:8000/<whatever was after the hash sign> whenever the links are clicked. It's not robust and it needs to be modified for your circumstances, but maybe it works as a starting point.
var hashLinks = document.querySelectorAll('a[href^="#"]');
var i;
function hashLinkClicked(event) {
var hash, url, request;
// You probably want to allow default link behaviour here
event.preventDefault();
hash = this.hash;
// Cut hash character out of URL
url = 'http:/localhost:8000/' + hash.slice(1);
request = new XMLHttpRequest();
request.onreadystatechange = function () { /* Handle response here */ };
request.open('GET', url);
request.send();
}
for (i = 0; i < hashLinks.length; i++) {
hashLinks[i].addEventListener('click', hashLinkClicked);
}

Load PHP file with document.createElement()

How could I make this work? I want to load a php file like this:
Click button.
Call Javascript function.
In Javascript function create an img with src file.php.
This should force the loading of the php. Here is the code.
<script type="text/javascript">
var d;
function callSave() {
alert ('calling');
if (d) document.body.removeChild(d);
// d = document.createElement("script");
d = document.createElement("img");
d.src = "savepages.php";
//d.type = "text/javascript";
document.body.appendChild(d);
}
</script>
Then in savepages.php I do another alert to verify that the php is called and it isn't. Here is the savepages.php.
<?php
echo "alert('from the php');";
?>
The alert from the php doesn't happen. Is there a different element type that will force loading of the php? I don't have ajax installed, so I need a workaround like this.
Thanks.
You could use an iframe element
<script type="text/javascript">
var d;
function callSave() {
alert ('calling');
if (d) document.body.removeChild(d);
d = document.createElement("iframe");
d.src = "savepages.php";
document.body.appendChild(d);
}
</script>
Found out the better way to handle this. There is this simple code that explains how to call a javascript function from a form event and from that javascript function load a PHP file. The code found at http://daniel.lorch.cc/docs/ajax_simple/ is also given here:
<script type="text/javascript">
var http = false;
if(navigator.appName == "Microsoft Internet Explorer") {
http = new ActiveXObject("Microsoft.XMLHTTP");
} else {
http = new XMLHttpRequest();
}
function validate(user) {
http.abort();
http.open("GET", "validate.php?name=" + user, true);
http.onreadystatechange=function() {
if(http.readyState == 4) {
document.getElementById('msg').innerHTML = http.responseText;
}
}
http.send(null);
}
</script>
<h1>Please choose your username:</h1>
<form>
<input type="text" onkeyup="validate(this.value)" />
<div id="msg"></div>
</form>
validate.php
<?php
function validate($name) {
if($name == '') {
return '';
}
if(strlen($name) < 3) {
return "<span id=\"warn\">Username too short</span>\n";
}
switch($name) {
case 'bob':
case 'jim':
case 'joe':
case 'carol':
return "<span id=\"warn\">Username already taken</span>\n";
}
return "<span id=\"notice\">Username ok!</span>\n";
}
echo validate(trim($_REQUEST['name']));
?>