I have a quite large AngularJS application and one of the forms is giving me trouble. On this form users can write messages that are saved on the server into the database. However, 20% of the time, some kind of error is causing the message to be blank. I can see these empty messages in the database.
As far as I can tell the problem is happening on the client not the server. (My evidence for this is that I've added code on the server that logs all the form data the moment that the web request is received. When blank messages are saved into the database, I can see that the message text was already missing in these logs right at the start of the server-side process.)
So, I think it may be something to do with the way I send the data from the client. My JavaScript is as follows...
var params = {
"slotid": self.slot.slotid,
"personid": self.personid,
"message": self.slot.message
};
$http({
method: 'POST',
url: '/restapi/confirmationmessage.aspx',
data: $.param(params),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
})
When it works, the form data on the server looks like this:-
slotid=SOME-GUID8&personid=ANOTHER-GUID&message=the+message+goes+here
When it fails it looks like this:-
slotid=SOME-GUID8&personid=ANOTHER-GUID&message=
The web page that accepts the message input is written using Bootstrap and the relevant fragment is below. The submit button is disabled if the textarea box is empty, so blank messages shouldn't ever happen!
<div class="form-group">
<textarea class="form-control" ng-model="slot.message" placeholder="Enter your message here..." rows="8"></textarea>
</div>
<button type="button" ng-click="ctrl.areyousure('message', slot, '');" ng-disabled="slot.message==''" class="btn btn-default">
<span class="glyphicon glyphicon-envelope"> </span>
<span>Send message</span>
</button>
In case it helps, my back-end is written in ASP.NET using C#.
Can anyone explain why the message parameter is sometimes empty? It is an intermittent fault, so I think it might have something to do with unusual characters in the message, but I've tried, commas, quotes, double quotes, and semi-colons, but they all worked fine. Could it be a limitation in the function $.param()?
It would also be useful to get some suggestions about how I could add some logging to my client-side code to help diagnose the problem, or any similar idea to help me solve this.
Thanks in advance.
Adam
your initial value for slot.message will be either null or undefined, so you should add those cases as well.
But this is not the right way checking for required value. You should use ng-required attribute, here is an example of using form-ng-required Angular form validation ng-disabled not working
Related
I have html and css code for a basic quiz template. I want to give the user the ability to make their own custom quiz.
Example: I have created my own math quizzes, science quizzes, etc, that the user can take. I am looking for the ability that Users can make their own personal quiz.
You don't append users input to your code. You should have your quiz as a data and let the user update the data by adding their quiz.
The structure of a form looks like this:
<form method = 'post' action='./handleSubmission/'>
<label>Question 1: </label>
<input type='text' class='question' name='question1'>
<label>Answer 1: </label>
<input type='text' class='answer' name='answer2'>
<label>Question 2: </label>
<input type='text' class='question' name='question2'>
<label>Answer 2: </label>
<input type='text' class='answer' name='answer2'>
<button>Submit</button>
</form>
(You can find all the different input types here. You might want another type for multiple choice questions.
When the user clicks on submit, the default behaviour is that the content of the form will be sent as an http request to the action url. if you set post as method, the method will be POST. If you set get as method, the method will be GET.
Now, in order to do something useful with it, there needs to be a server-side script at './handleSubmission/' or whatever url you put in here, that can read the sent data and upload it to some place where you store the data for your quizzes. This can be either a database or a repository containing some files.
I'd go for json files. Because json files can very easily be decoded and used in any web scripting language.
In PHP for example you'd get the content of the form through a special array called $_GET (or $_POST depending on the method).
You'd then have access to 'question1' with $_GET['question1'].
You'd then have to find a way to put that data into a json file.
To use the content of the json files, you can either use a backend script or a frontend script like javascript.
Are you already using a scripting language for the backend such as PHP or Python? Or do you focus on frontend?
If you want to focus on javascript and frontend, this is the alternative:
<form>
//...
<button id='btn-submit'>Submit</button>
</form>
As you can see, i ommited action and method because in this alternative we don't want to send the form to the server. What we'll do is, when the button is clicked, we'll capture the content of the form without refreshing the page, and then send it a Backend-as-a-service like Google Firebase.
const submitButton = document.querySelector('#btn-submit');
submitButton.addEventListener('click', (e) => {
/* important! prevents the default behaviour which is to submit the form */
e.preventDefault();
const data = [];
/* do stuff here to retrieve the data from form like: */
const questionInputs = document.querySelector('.question');
const answerInputs = document.querySelector('.answer');
for(let key in questionInputs){
data[key] = {
question: questionInputs[key].value;
answer: answerInputs[key].value;
}
}
sendToFirebase(data);
});
You'd then have to write the sendToFirebase function.
Firebase requires making an account, starting a project by giving a name etc. Then it gives you the code to put in your app and you can read the documentation about how to upload data to the Realtime Database.
I strongly prefer the first option however. Because i think in this case the Firebase Realtime Database would be a bit cumbersome to use compared to just setting up a small backend script that generates json files.
This post is more a question than an actual issue with code.
So for a long time when I had to display for example a list of items from database, I used to display the Id (primary key in the table) directly in the HTML like this for example :
<div id="1"></div>
<div id="2"></div>
<div id="3"></div>
<div id="4"></div>
So like this when I wanted to do an Ajax request of the current clicked item, it was easy because I just had to retrieve the attribute from the html like this :
$.ajax({
url: '/api/Item/'+$(this).attr('id'),
type: 'GET',
})
.done(function() {
console.log("success");
})
.fail(function() {
console.log("error");
})
.always(function() {
console.log("complete");
});
That's only after browsing a lot of websites that I noticed that nobody display the primary key (Id) directly in the HTML. But somehow they could still do ajax request to the API using the Id of the clicked item. So my question is : How can I get the current clicked Id to do my ajax request without displaying anywhere. I mean how does these websites manage to do that ? Maybe they get list from server that they use in the client then ? But it still does not explain how they manage to get the current clicked Id.
Appreciate your thoughts and suggestions on this.
Example of website : https://www.toneden.io/
The chat at the bottom right when connected see network and web browser console.
To get response from the server, you have to request something. In this case, you are saying i don't want to display primary key anyware in html side and get result from server. my suggestion on this, In php > you can use binary number instead of primary key and convert back to number and use acc. to requirements. Example :- decbin() and bindec()
There's nothing wrong with displaying an id. I've appended the database id such as id="game_1281" in cases where I only want to refer to the DOM in response to a server push update. Another option is to use a data attribute like so: data-id="1281". This allows you to get the value without any messy parsing before sending it to the server.
Referencing a unique id is not a security issue. Just make sure you are doing the appropriate server-side checks to ensure that the action taken is possible for that user based on various constraints and privileges.
I have a html page with some buttons, one of my buttons is as following:
<input class="contentLink" type="button" value="Questionnaire" onclick="validate(<?php urlencode('/my-site/Tools/Learning_Strategies/Questionnaire.php'); ?>)"/>
Essentially when this button is clicked, it passes the urlencoded-string literal '/my-site/Tools/Learning_Strategies/Questionnaire.php' into the javascript method validate:
function validate(url){
alert(url);
location.href="/my-site/Session/redirectMe.php?loc="+url;
}
What I am trying to do is get '/my-site/Session/Questionnaire.php' from the html page accessible from the redirectMe.php. This is being setup in the
location.href="/my-site/Session/redirectMe.php?loc="+url;
which leads to my redirectMe.php file:
<?php
require "SessionAuthenticator.php";
Session_start();
if(validateSession()===true){//validateSession() is defined inside SessionAuthenticator.php
echo $_GET["loc"];
//header("Location: ".$_GET["loc"]);
}else{
header("Location: /my-site/LoginPage/index.php");
}
?>
The issue is during both of the alert and echo, the encoded string literal came out as "undefined", which means the following line:
header("Location: ".$_GET["loc"]);
will really look like this:
header("Location: undefined");
And therefore look for 'undefined' in the current directory and break the website.
This all works perfectly if there is no encoding as following:
<input class="contentLink" type="button" value="Questionnaire" onclick="validate('/my-site/Tools/Learning_Strategies/Questionnaire.php')"/>
But... No encoding is bad right?
If you are wondering why you don't see a decode method being used...
The webserver will arrange for $_GET to have been urldecoded once already by the time it reaches you! - Matt Johnson ¶ # http://php.net/manual/en/function.urldecode.php#48481
Require and include will not work, as redirectMe.php would be executed before the user even sees the page. This should only happen when the user clicks the button. That is why I am using a javascript function to start redirectMe.php.
I've tried ajax, however this didn't work. After talking with an experienced programmer who I know personally, I've been told that ajax can't help me here. This because Ajax would be redirected to '/my-site/Tools/Learning_Strategies/Questionnaire.php', but not the client (User).
To clearly state my question:
Why is the urlencoded coming up as 'undefined' when echo-ed/alert-ed? How do I fix this?
As for programs/web servers/etc I am using...
Sublime 3 (text editor)
Wamp (64BIT)(all-in-one package) # http://www.wampserver.com/en/
Apache 2.4.17
PHP 7
MySQL 5.7.9
I am open to other means of getting what I am trying to do done.
However, I am not open to changing web servers/programs etc (except sublime 3 since it is just a text editor.... but why would that need to be required?).
Furthermore, whatever means of getting this done needs to support the browsers/platforms as stated below.
The website must support:
(Browsers)
IE 8 and up, and latest versions of Microsoft Edge, Firefox, Chrome and Safari.
Cross-Platform:
Windows 7 and up, and the latest versions of Mac OS, IOS and Android
Why is the urlencoded coming up as 'undefined' when echo-ed/alert-ed?
Because the PHP doesn't output anything.
<input class="contentLink" type="button" value="Questionnaire" onclick="validate(<?php urlencode('/my-site/Tools/Learning_Strategies/Questionnaire.php'); ?>)"/>
Gives you:
<input class="contentLink" type="button" value="Questionnaire" onclick="validate()"/>
… once you run it through a PHP parser.
You need to:
echo the result so something appears there
wrap it in quotes (with json_encode so any escaping needed is also taken care of) so that it will be treated as a string and not a variable name.
I have a express route;
router.get('/uni/:queryst', function (req, res) {
var choice = req.params.queryst);}
Where basically I use the queryst value from the URL to use it to query something in my database. On the front end, I need to have an input field where the user types the choice and hits submit and then it translates to something like /uni/valuehere on the browser and sending GET to express where it gets caught by the router I wrote above. I don't know how can I make the input field of HTML turn into a URL of the format /uni/valuehere .
As for testing the code initially I was directly typing the URL manually with the value I intended to verify to check if the data passed. Well, users are not going to type URL's directly to search, they will need a form and that is what I can't get my head around to how to turn the input field into a URL in a format /uni/WhateverTheUserHasTypedInTheFieldShouldAppearHere
Thanks in advance for the help. I am self learning the MEAN stack and have come a long way. I need support of experienced developers as I am currently stuck here.
While sending the request write (in controller):
$http.get('/uni/'+queryst).success(function(response){
// Write code using response
});
While on the server side write:
$http.get('/uni/:queryst',function(req,res){
var choice= req.params.queryst
// Code ....
});
I'm defining a delete function in which, there's a delete button in each row, sending the ObjectID of that specific record to my Server Side, therefore, this ObjectId will be checked with the one stored in the database, resulting in deletion of that certain record, so far I could have make a good progress sending data's over, and checking on it, but I"m suspecting the ObjectId being sent, requires some sort of casting. Currently, the code and responses are as below;
Front-End (Index.Html)
<a href="#" class="list-group-item active" >
List Of Notes
</a>
<a href="#" class="list-group-item" ng-repeat="r in retrieve" >
{{r.create_at}}
<button style="float:right" type="button" ng-click="delete_note(r.ObjectId)"
class="btn btn-danger btn-xs">
Delete <i class="fa fa-trash"></i>
</button>
</a>
AngularJS (main.ctrl.js)
$scope.delete_note = function (data_id) {
$http.get('/delete_note', {
params: data_id
}).success(function(data){
console.log(data)
});
}
Back-End (Root.py)
#cherrypy.expose
#cherrypy.tools.json_out()
#cherrypy.tools.json_in()
def delete_note(self,*args,**kwargs):
res2=self.my_app.delete_note(kwargs)
return "<h1>delete success </h1>" +str(res2)
pass
Back-End (App.py)
def delete_note(self, index):
return self.db.notes.remove({'_id': index})
The current message appears in Google Chrome Console.log is this :
<h1>delete success </h1>{'ok': 1, 'n': 0}"
Which is obviously stating that, nothing has been changed within the database, I'm using Cherrypy, Mongodb, and Angularjs, any consideration is appreciated.
It'll be hard to locate the exact problem, but there are a few things that call for attention:
As nnnnnn already pointed out, nesting a button in an anchor (a) element is odd and might lead to weird issues.
The directive ng-click="delete_note(r.ObjectId)" looks odd: Does your python code really remap the _id field to a field called ObjectId? ObjectId is the type of (default) keys in MongoDB, the convention for the name is _id.
To find out, take a look at the network inspector when you GET the original data (i.e., $scope.retrieve) - what does it send? It's also helpful for debugging to output <pre>{{retrieve | json}}</pre> so you can see what ends up at angular
You're apparently deleting using a GET. While there's nothing that prevents you from doing that, writing with GETs is bad practice. If you possibly can, delete using an HTTP DELETE. If that's completely impossible for whatever reason, at least use a POST. But a GET should be nullipotent, i.e. it shouldn't change the server state at all.
The parameter to a REST request should be part of the URL, so your delete should read
DELETE /notes/:noteId, e.g. DELETE /notes/54fadec1e4259ded64c7576a
Putting the identifying parameter somewhere else violates the idea of resource urls.