Why are my inputs not resetting? - html

The below code generates several forms depending on data returned from the server. Everything generates fine, but after clicking on an AnswerOpenQuestion button the input does not clear/reset. What's going on here?
angularJs code:
var availableInterviewController = function($scope, $http) {
// define initial model
$scope.interviews = [];
// retrieve available interviews
$http.get('/api/UserInterviewsApi/AvailableInterviews')
.success(function(data) {
// update interviews
$scope.interviews = [];
$scope.interviews = data;
});
// define open question answer selection
$scope.Answer = "";
// define multiple choice selection
$scope.selectedChoice = "";
// define answer open question button
$scope.AnswerOpenQuestion = function() {
$scope.Answer = ans;
alert(q.Question + ' and ' + $scope.Answer);
$scope.Answer = ''; // <---This is not clearing/resetting the HTML form inputs
};
// define answer multiple choice button
$scope.AnswerMultipleChoice = function() {
//
};
};
// assign the new controller to the main angular app
myAngApp.controller('availableInterviewCtrl', availableInterviewController);
Html code:
<form class="form-group" ng-repeat="q in inter.Questions">
<fieldset style="display: inline-block;">
<legend>Question {{$index + 1}}</legend>
<!--Open Ended-->
<div class="form-group" ng-show="q.MultipleChoices.length === 0">
<label for="{{'quest-' + $index}}">
<strong class="text-info">{{q.Question}}</strong><br />
</label>
<input name="openQuestion" id="{{'quest-' + $index}}" type="text"
class="form-control" ng-model="Answer" />
<button ng-click="AnswerOpenQuestion()">Answer</button><br />
<span class="text-info">
asked by {{q.AskedByUserName ==
'Administrator' ? 'staff' : q.AskedByUserName}}
</span>
</div>
<!--Multiple Choice Question-->
<div class="form-group" ng-show="q.MultipleChoices.length > 0">
<label for="{{'quest-' + $index}}">
<strong class="text-info">{{q.Question}}</strong>
</label>
<div>
Select an answer:
<label ng-repeat="x in q.MultipleChoices">
<input name="currentChoice" type="radio" value="{{x.Id}}"
ng-model="selectedChoice" />
{{x.Choice}}
</label>
<button ng-click="AnswerMultipleChoice()">Answer</button><br />
<span class="text-info">
asked by {{q.AskedByUserName ==
'Administrator' ? 'staff' : q.AskedByUserName}}
</span>
</div>
</div>
</fieldset>
</form>
UPDATE - Solution
AngularJs:
// define open question answer selection
$scope.OpenAnswer = { Answer: '' };
// define answer open question button
$scope.AnswerOpenQuestion = function (q, ans) {
$scope.OpenAnswer.Answer = ans;
alert(q.Question + ' and ' + $scope.OpenAnswer.Answer);
// clear the input
$scope.OpenAnswer.Answer = '';
};
Html:
<input id="{{'quest-' + $index}}" type="text"
class="form-control" ng-model="OpenAnswer.Answer" />

Don't use the scope as a model instead make an object that wraps the data model and assign it to a property of the scope.
$scope.myModel = {Answer:''}
Also don't use value in most cases ngmodel is all you need for two way binding.
In js strings are immutable so the original reference is not being updated instead a new string is being made, the digest cycle won't see this as a change to the original string.

Related

How can I create a loop for Chat Bubbles?

I want to develop a loop for chat bubbles. Every time I write a message, a bubble should be created and be on the right. When the chat partner replies, the message should be on the left in the bubble. How can I develop this loop?
My current code is this one:
<div class="Webview">
<div class="message_container" id="myForm"></div>
<form class="send_container">
<input id="textField" type="text">
<p>
<input type="button" id="theButton" value="Nachricht absenden!" onclick="document.getElementById('myForm').innerHTML=document.getElementById('textField').value" />
</p>
<h3>
<div id="div"></div>
</h3>
</form>
</div>
OK, it is not add messages to the DOM in loops, but just add message on Enter on the trigger that sending the message.
If you want to add value from Text Field such as text input,
You probably want to do two steps:
Getting the value from the input
Inject the value into a balloon template (html) and then into the DOM.
Then, you should add Javascript scope into your html or just include js file that contain the following function:
function addMessage() {
// Add XSS validation
const $messages = document.getElementById('myForm');
const $textElement = document.getElementById('textField');
const newMessage = '<div class="message-balloon">' + $textElement.value + '</div>';
$messages.innerHTML += newMessage;
return false;
}
<input type="button" id="theButton" value="Nachricht absenden!" onclick="addMessage()" />
In jQuery it will be like this (in the js scope of course):
$("#theButton").off('click').on('click', function() {
e.preventDefault();
const $messages = $('#myForm');
const $textElement = $('#textField');
const newMessage = '<div class="message-balloon">' + $textElement.value + '</div>';
$messages.html += newMessage;
return false;
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="button" id="theButton" value="Nachricht absenden!" />
Hope it helps :)
Good luck

Angularjs Parse value from input box to controller

I have an input box of quantity that the user can change it's value by clicking the - and + buttons. The problem is that if I entre the value directly in the input box I can parse this value to my controller. If I change the value by clicking the buttons + or - I can not parse the value to controller, it keeps always the old value. Can anyone help me?
<button
onclick="var result = document.getElementById('qty'); var qty = result.value; if( !isNaN( qty ) && qty > 0 ) result.value--;return false;"
class="reduced items-count"
type="button"
>
<i class="fa fa-minus"> </i>
</button>
<input
type="text"
class="input-text qty"
title="Qty"
maxlength="12"
id="qty"
name="qty"
ng-init="qty='1'"
ng-model="qty"
>
<button
onclick="var result = document.getElementById('qty'); var qty = result.value; if( !isNaN( qty )) result.value++;return false;"
class="increase items-count"
type="button"
>
<i class="fa fa-plus"> </i>
</button>
And my controller,
$scope.$watch('qty', function (val) {
if (val) {
alert("qty2:" + val);
}
});
I don't quite understand what you are trying to implement, but you can use ng-click on your buttons to execute some function in your controller.
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.qty = 0;
$scope.change = function(value) {
$scope.qty += value;
$scope.changed(); // execute after update
}
$scope.changed = function() {
/*
Do what you want after the update,
but $scope.qty is dynamic anyway
*/
//alert("qty: " + $scope.qty);
}
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-app="myApp">
<div ng-controller="myCtrl">
<button ng-click="change(-1)" type="button">-</button>
<input type="number" ng-model="qty" ng-change="changed()" />
<button ng-click="change(1)" type="button">+</button>
<br/>{{qty}}
</div>
</div>
</body>
</html>
This is totally the wrong approach... never use dom methods in angular app like that.
Use ng-click to modify the ng-model property. Also always follow the golden rule of making sure you have a dot in ng-model
angular
.module('app', [])
.controller('Ctrl', function($scope) {
$scope.data = {
qty: 0
}
$scope.updateQty = function(amt) {
$scope.data.qty += amt
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.min.js"></script>
<div ng-app="app" ng-controller="Ctrl">
<button ng-click="updateQty(-1)">-1</button>
<input ng-model="data.qty">
<button ng-click="updateQty(1)">+1</button>
</div>

Failure handler in Google Apps Script receives object different from what is thrown on server side

My app sends submitted form data to this server-side function:
function processFormData(data)
{
data = JSON.parse(data);
// validate data
var errorObject = {},
potholeErrors = createErrorObjectFor('pothole'),
intervalSizeErrors = createErrorObjectFor('intervalSize');
// make sure numbers are actual numbers and not NaN's.
if (!validateNumber(data.potholeWidth))
{
potholeErrors.messages.push(errorTypes.NOT_A_NUMBER);
errorObject.potholeWidth = potholeErrors;
}
if (!validateNumber(data.intervalSize))
{
intervalSizeErrors.messages.push(errorTypes.NOT_A_NUMBER);
errorObject.intervalSize = intervalSizeErrors;
}
// make sure numbers are within their respective bounds (handled by handleErrors())
errorObject = handleErrors(data, errorObject);
// if intervalSize doesn't divide potholeWidth, make it so
if (data.potholeWidth % data.intervalSize > 0) data.potholeWidth = nextMultiple(data.intervalSize, data.potholeWidth);
// if there is anything in errorObject, throw it
if (Object.getOwnPropertyNames(errorObject).length != 0)
{
Logger.log('errorObject == ' + JSON.stringify(errorObject, null, '\t'));
throw errorObject;
}
// createSpreadsheet
return createSpreadsheet(data.spreadsheet, data.potholeWidth, data.intervalSize);
}
which, upon success, does exactly what it's supposed to do. However, when end-user enters any invalid input, the object the server-side throws back is different than the one they end up getting. I tried entering a pothole width that was too small. When I inspected Logger on server-side, I saw this correct output:
however, in the Developer console, I see:
The code that communicates data to the server looks like:
function updateURL(url)
{
// activate button
$('#input[type="submit"]').prop('disabled', '');
// change href of #spreadsheetLink
$('#spreadsheetLink').attr('href', url);
// unhide the link's container if hidden
if ($('#spreadsheetLink').parent().hasClass('hidden')) $('#spreadsheetLink').parent().removeClass('hidden');
// hide the 'Loading...' element
if (!$('#loading').hasClass('hidden')) $('#loading').addClass('hidden');
}
function emailLink()
{
google.script.run.withSuccessHandler(function() {
$('#emailLink').next().text('E-mail message has been sent!');
$('#emailLink').prop('disabled', 'disabled');
}).emailLink($('#spreadsheetLink').attr('href'));
}
function handleFails(failData)
{
var DEBUG = true;
if (DEBUG) console.log('failData == ' + JSON.stringify(failData, null, '\t'));
// hide 'Loading...' element
if (!$('#loading').hasClass('hidden')) $('#loading').addClass('hidden');
// for now, let's ignore any Errors/TypeErrors.
if ((!failData instanceof Error) && (!failData instanceof TypeError))
{
// for now, if there were any errors with any of the fields, simply mark them as .invalid
if ((failData.potholeWidth) && (failData.potholeWidth.messages.length > 0))
{
if (!$('#potholeWidth').hasClass('invalid')) $('#potholeWidth').addClass('invalid');
}
if ((failData.intervalSize) && (failData.intervalSize.messages.length > 0))
{
if (!$('#intervalSize').hasClass('invalid')) $('#intervalSize').addClass('invalid');
}
}
}
function submitFormData()
{
// hide spreadsheetLink container if not already done, and clear its <span> element if not already clear
var spreadsheetLinkContainer = $('#spreadsheetLink').parent(),
spanElement = $('spreadsheetLinkContainer').find('span');
if (!$(spreadsheetLinkContainer).hasClass('hidden')) $(spreadsheetLinkContainer).addClass('hidden');
if ($(spanElement).text() != '') $(spanElement).text('');
// get all data
var potholeWidth = parseNumberField('potholeWidth'),
intervalSize = parseNumberField('intervalSize') || defaults.get('intervalSize'),
concaveEdges = $('input[name="concaveEdges"]').filter(function() { return $(this).prop('checked'); }).next().text() === 'Yes',
spreadsheetName = parseField('spreadsheetName') || defaults.get('spreadsheetName');
// make button inactive
if (($(this).prop('tagName')) && ($(this).prop('tagName').toLowerCase() == 'input')) $(this).prop('disabled', 'disabled');
// show "Loading..." element
if ($('#loading').hasClass('hidden')) $('#loading').removeClass('hidden');
// submit this data to the server
google.script.run.withSuccessHandler(updateURL).withFailureHandler(handleFails).processFormData(JSON.stringify({
potholeWidth: potholeWidth,
intervalSize: intervalSize,
concaveEdges: concaveEdges,
spreadsheet : spreadsheetName
}));
}
and the HTML looks something like this:
<form>
Place straightedge/yardstick along width of pothole such that it points at the corners, <a class="showImage">like this</a>
<span class="row">
<label class="firstColumn seventeenTwentieths">Pothole width (in inches): </label>
<input type="text" class="secondColumn tenth numberField" id="potholeWidth" required />
</span>
<span class="rowTight">
<label class="firstColumn seventeenTwentieths">Interval size (in inches, default 1 inch): </label>
<input type="text" class="secondColumn tenth numberField" id="intervalSize" value="1" />
</span>
<div class="rowTight">
<label class="firstColumn">Do any of the edges intersect the straightedge/yardstick other than at the corners?</label>
<div class="secondColumn">
<span>
<input type="radio" name="concaveEdges" id="yesConcaveEdges" />
<label for="yesConcaveEdges">Yes</label>
</span>
<br>
<span>
<input type="radio" name="concaveEdges" id="noConcaveEdges" checked />
<label for="noConcaveEdges">No</label>
</span>
</div>
</div>
<span class="rowTight">
<label class="firstColumn half">Spreadsheet name: </label>
<input type="text" class="secondColumn nineTwentieths" id="spreadsheetName"/>
</span>
<span class="center row">
<button class="center" id="clearForm">Clear</button>
<input type="submit" class="center action" value="Create spreadsheet" />
</span>
</form>
<span id="loading" class="row center fullWidth hidden">
Loading...
</span>
<span class="row center fullWidth hidden">
Here is your spreadsheet
<button id="emailLink">E-mail me the link</button>
<span></span>
</span>
What is that object the client actually gets and how to make sure that it's getting the object the server actually throws?
I fixed it.
What I did
In code.gs
Instead of simply throw errorObject;, I said throw JSON.stringify(errorObject);
In JavaScript.html file
in handleFails(), I converted the string the server-side threw back into object (failData = JSON.parse(failData)) to use it. It outputted it correctly, and all is well.
What I learned
Any time the server is either giving or receiving data, it MUST be in the form of a string! (Use JSON.stringify() to make that data a string!)

How to make Razor not display special characters as html

The page I'm working on displays content from a database in readonly input box. My problem is that it's displaying any special characters as the html code (ie: & displays as &). How do you get the code to display properly?
I'm using QuerySingle to connect to the database, don't know if that makes a difference. I'm new to using Razor. Any help is much appreciated.
Code in question:
var queryloan = "SELECT * FROM loans WHERE LoanId = #0";
var queryloandata = db.QuerySingle(queryloan, queryformstatus_submitted.doc_loanid);
<form class="jotform-form" action="submit-form.cshtml?isadmin=#(isadmin)&loanid=#(loanid)" method="post" name="form_30905105572145" id="30905105572145" accept-charset="utf-8">
<input type="hidden" name="formID" value="30905105572145" />
<input type="hidden" name="doc_id" value="#doc_id" />
<div class="form-all">
<ul class="form-section">
<li id="cid_3" class="form-input-wide">
<div class="form-header-group">
<h2 id="header_3" class="form-header">
Borrower Sources & Uses Summary
</h2>
#if (queryformstatus_submitted.doc_approval == "Pending Approval" || queryformstatus_submitted.doc_approval == "Approved")
{
<text><br />
<br />
<div class="error">
This form has already been submitted and cannot be edited. It is for reference only.</div></text>
}
#if(userid != queryformstatus_submitted.doc_userid){
<text><br/><br/><div class="error">You may not edit this form. It is for reference only.</div></text>
}
</div>
</li>
<li class="form-line" id="id_4">
<label class="form-label-left" id="label_4" for="input_4">
1. Property Name:
</label>
<div id="cid_4" class="form-input">
<input type="text" class=" form-textbox" id="input_4" name="q4_1Property" size="40" value="#Helpers.checkEmptyPreFill(queryinputvalue,"q4_1Property",queryloandata.LoanName)"/>
</div>
</li>
I'm not sure but I believe it may be something in this helper function that's causing the html code:
#helper checkEmptyPreFill(IEnumerable<dynamic> queryinputvalue, string field_id, string defaultval, int cloned = 0) {
var reqValue = queryinputvalue.FirstOrDefault(r => r.field_name.Equals(field_id));
var return_value = "";
if(reqValue != null){
return_value = reqValue.field_data;
} else {
return_value = defaultval;
}
if(cloned == 1){
return_value = "";
}
#return_value
}
The razor helper returns a HelperResult object so you'll have to convert it to a string before you can call HtmlDecode on it. Replace:
#Helpers.checkEmptyPreFill(queryinputvalue,"q4_1Property",queryloandata.LoanName)
with the following:
#HttpUtility.HtmlDecode(Helpers.checkEmptyPreFill(queryinputvalue,"q4_1Property",queryloandata.LoanName).ToString())
I would also suggest that you move some of the logic and data access code out of your view and into a controller but this should give you the result that you'e after.

How do preserve leading and trailing whitespace when using an input tag?

I am playing with Angular and writing a Regex tester.
Problem is leading whitespace is trimmed when I enter data. See example jsfiddle here:
So when the page loads I have the RegEx "^\d+$".test(" 123 ") which results in "No Match", But if you enter an extra leading or trailing space in the Candidate box:
The leading and trailing spaces are removed from my variable
The result changes "Match"
Here is my HTML:
<div id='ng:app' class='ng-app: myApp' ng-app='myApp'>
<div ng-controller="Controller">{{addTodo2()}}
<form novalidate class="simple-form">Pattern:
<input type="text" ng-model="pattern" />Candidate:
<input type="text" ng-model="candidate" />
<br />.{{candidate}}.
<br>.{{candidate2}}.</form>
</div>
</div>
And here is the associated JavaScript:
function Controller($scope) {
$scope.pattern = "^\\d+$";
$scope.candidate = " 123 ";
$scope.candidate2 = " 123 ";
$scope.addTodo2 = function () {
var str = "Javascript is an interesting scripting language";
var re = new RegExp($scope.pattern, "g");
var result = re.test($scope.candidate);
if (result) {
return "Match22";
} else {
return "No Match22";
};
};
}
var myapp = angular.module('myApp', []);
Updated the fiddle, added ng-trim="false" to the input tags
http://jsfiddle.net/T2zuV/12/
<div id='ng:app' class='ng-app: myApp' ng-app='myApp'>
<div ng-controller="Controller">{{addTodo2()}}
<form novalidate class="simple-form">Pattern:
<input type="text" ng-model="pattern" ng-trim="false"/>Candidate:
<input type="text" ng-model="candidate" ng-trim="false"/>
<br />.{{candidate}}.
<br>.{{candidate2}}.</form>
</div>
</div>