Angular-Calling function result in HTML - html

I have a function in my ts file:
makeid(length) {
var result = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for ( var i = 0; i < length; i++ ) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
And what I want is to return result of this function in my html. I can call a funtion in html like:
<input [readonly]="true" formControlName="caseId" matInput placeholder="Radni nalog br:" value="{{ makeid(15) }}">
But every time I click anywhere, it changes the value, and I'm getting an error:
ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.

Every time the component reloads it will change because the function will run again.
To keep the value of the first call use a variable to store the value on ngOnInit()
Examle:
x: string;
ngOnInit(){
this.x = makeid(15)
}
makeid(length) {
var result = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for ( var i = 0; i < length; i++ ) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
And in the HTML:
<input [readonly]="true" formControlName="caseId" matInput placeholder="Radni nalog br:" [value]="x">

You should use [( ngModel )] or put a variable in your component.ts file and change that variable with your function and html will change automatically:
something like this
<input id="Last Name" name="Last Name" type="text" [(ngModel)]="user.lastName" />
this stackblitz will help you https://stackblitz.com/edit/angular-6-value-changes-v2?file=src%2Fapp%2Fapp.component.html

Related

Grouping the tables with dropdown box

I am a beginner in google app script. So right now I am doing a project where users can sign in and can view their payment history. So for now it is just showing from 2020 until 2021. So I want your guys help on creating a dropdown box which states (eg : 2020 , 2021 ) so maybe if the user clicks 2020 then they can see the payment history of 2020 only. I really need your guys help in this thing. I have attached the link to my google app script and a image to explain myself better. Thank you guys.
https://script.google.com/d/1DdRKqUX__-ZITUgTZanQ_A7hUL1kcc0TZOeFmn58wYsX_o_7cqNExnYo/edit?usp=sharing - Link to my appscript
First image
Second Image
Here is a sample code you can refer with:
WebAppLogin.html (modifications)
<script>
function GetRecords() {
var spin = "<span class=\"spinner-border spinner-border-sm\" role=\"status\" aria-hidden=\"true\"></span>";
spin += " Loading...";
document.getElementById("LoginButton").innerHTML = spin;
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
google.script.run.withSuccessHandler(function(output) {
console.log(output);
var username = output[1];
var name = output[2];
if(output[0] == 'TRUE') {
document.getElementById("errorMessage").innerHTML = "";
document.getElementById("currentUser").value = username;
google.script.run.withSuccessHandler(displayTable).GetRecords(username,"None");
} else if(output[0] == 'FALSE') {
document.getElementById("firstLastName").innerHTML = "";
document.getElementById("currentUser").value = "";
document.getElementById("myFilter").innerHTML = "";
document.getElementById("errorMessage").innerHTML = "Failed to Login";
document.getElementById("LoginButton").innerHTML = "Login";
}
}).checkLogin(username, password);
}
function filter(){
var filterStr = document.getElementById("filterYear").value;
var user = document.getElementById("currentUser").value;
google.script.run.withSuccessHandler(displayTable).GetRecords(user,filterStr);
}
function displayTable(result) {
var ar = result.data;
var filterString = result.filter;
var username = document.getElementById("currentUser").value;
if(ar.length > 0) {
var displayTable = '<table class=\"table\" id=\"mainTable\" >';
displayTable += "<tr>";
displayTable += "<th>Month</th>";
displayTable += "<th>House Number</th>";
displayTable += "<th>Street</th>";
displayTable += "<th>Payment Status</th>";
displayTable += "</tr>";
ar.forEach(function(item, index) {
displayTable += "<tr>";
displayTable += "<td>"+item[0]+"</td>";
displayTable += "<td>"+item[1]+"</td>";
displayTable += "<td>"+item[2]+"</td>";
displayTable += "<td>"+item[3]+"</td>";
displayTable += "</tr>";
});
displayTable += "</table>";
} else {
var displayTable = "<span style=\"font-weight: bold\" >No Records Found</span>";
}
var filter = '';
if(filterString.length > 0) {
filter += '<label for="years" style="font-size: 20px">Years</label><br><select class="form-control form-control-sm" id="filterYear" name="years" required><option value="" selected>Choose...</option>';
filterString.forEach(str => {
filter += '<option value="'+str+'">'+str+'</option>';
});
filter += '</select><button class="btn btn-primary" type="button" id="FilterButton" onclick="filter()" >Submit</button>';
}
//var filter = '<label for="years" style="font-size: 20px">Years</label><br><select class="form-control form-control-sm" id="filterYear" name="years" required><option value="" selected>Choose...</option><option value="2020">2020</option><option value="2021">2021</option></select><button class="btn btn-primary" type="button" id="FilterButton" onclick="filter()" >Submit</button>';
document.getElementById("digitalgoods-030521182921-1").style.display = "block";
document.getElementById("displayRecords").innerHTML = displayTable;
document.getElementById("firstLastName").innerHTML = "USER: " + name;
document.getElementById("myFilter").innerHTML = filter;
document.getElementById("LoginButton").innerHTML = "Login";
document.getElementById("username").value = '';
document.getElementById("password").value = '';
}
</script>
<div>
<h2 id="firstLastName">
</h2>
</div>
<input type="hidden" id="currentUser" value=""/>
<div id ="myFilter" class="form-group">
</div>
</div>
<div id="displayRecords" style="padding: 10px;" >
</div>
Modifications done:
Include empty form-group class
Include hidden input to hold current logged-in user
Create a reusable function displayTable()
Create an html content for the drop-down filter. See variable filter.
Include another argument when calling GetRecords(username, filter)
Create a new function filter()
During initial log-in, filter will be set to "None". filter will be set depending on the option selected
Code.gs (modifications)
function GetRecords(username,filter) {
var filteredDataRangeValues = GetUsernameAssociatedProperties(username);
var resultArray = GetPaymentRecords(filteredDataRangeValues,filter);
var resultFilter = getYears();
result = {
data: resultArray,
filter: resultFilter
};
return result;
}
function getYears() {
var ss= SpreadsheetApp.openByUrl(url);
var yearSheet = ss.getSheetByName("Configuration");
var getLastRow = yearSheet.getLastRow();
var return_array = [];
for(var i = 2; i <= getLastRow; i++)
{
if(return_array.indexOf(yearSheet.getRange(i, 2).getDisplayValue()) === -1) {
return_array.push(yearSheet.getRange(i, 2).getDisplayValue());
}
}
return return_array;
}
function GetPaymentRecords(userProperties,filter) {
var transpose = m => m[0].map((_, i) => m.map(x => x[i]));
var resultArray = [];
var ss = SpreadsheetApp.openByUrl(url);
var displaySheet = ss.getSheetByName(streetSheetName);
var addressValues = displaySheet.getRange("B:C").getValues();
var paidMonthValues = displaySheet.getRange("G:AD").getValues();
//Logger.log(addressValues);
//Logger.log(transpose(paidMonthValues));
userProperties.forEach((v, i) => {
var userHouseNumber = v[1];
var userStreet = v[2];
var column = addressValues.reduce(function callbackFn(accumulator, currentValue, index, array) {
if (currentValue[0] == userHouseNumber && currentValue[1] == userStreet) {
return index
} else {
return accumulator
}
}, '');
//Logger.log(column);
Logger.log(filter)
Logger.log(paidMonthValues);
if(filter=="None"){
var result = transpose(paidMonthValues).map(function callbackFn(element, index, array) {
return [element[0], userHouseNumber, userStreet, element[column] || '']
});
}else{
var result = transpose(paidMonthValues).map(function callbackFn(element, index, array) {
if(element[0].includes(filter))return [element[0], userHouseNumber, userStreet, element[column] || '']
});
}
resultArray = resultArray.concat(result);
//Logger.log(resultArray);
})
//Remove null elements
resultArray = resultArray.filter(element=>{
Logger.log(element!=null)
return element != null;
});
return resultArray;
}
Modifications done:
Modified GetRecords() and GetPaymentRecords() to include filter option
Add removal of null elements in the resultArray. (Null elements may exist when filter option was used due to the map() used)
Output:
(After user logged-in)
(After user selects a filter)
(UPDATE):
The following modifications where done to create a drop-box based on the list of years available in the configuration sheet.
WebAppLogin.html
displayTable() was modified that will accept an object as its parameter which contains an array data and an array of filter strings.
displayTable() was modified to update the drop-down options based on the filter strings available
Code.gs
getYears() was added that will read the sheet "Configuration" to get the filter string values
GetRecords() was modified to return an object which contains an array of record data and an array of filter strings.

Add 2 input values and show total

I have 2 'time' inputs for a start and end time.
When both inputs are completed I am wanting the 'total' field to automatically show the total between start and end (e.g 8 hours)
<input type='time' value="09:00" id="MondayStart" name='MondayStart' class='form-control'>
<input type='time' value="17:00" name='MondayEnd' id="MondayEnd" class='form-control'>
<input type="text" name="total">
I have tried following this script (http://jsbin.com/emoziw/1/edit?html,js,output) but cannot seem to change it to time
You have a default value so this is good.
You need to do something like this (using jQuery) :
$(".form-control").on('change', ()=>{
var $this = $(this);
var sum;
sum = /*do the sum calculation here*/;
$('input[name="total"]').eq(0).val(sum);
//if you put an id to the total then you can just use $(id here).val(sum)
});
This will, when the change event is triggered on any element having the form-control class, update the sum automatically.
PS:
I suggest to put a default value on the sum's holder (being of course the sume of the default values)
EDIT
I'd like to help you with the time calculation, so I made functions :
function doCalc($jq){//pass in the jqSelection that gets the two input
var $beg = $jq.eq(0);//first element with this class
var $end = $jq.eq(1);//second element with this class
var beg_t = {
h: getH($beg),
m: getM($beg)
}
var end_t = {
h: getH($end),
m: getM($end)
}
var elapsed = {
h: end_t.h - beg_t.h,
m: end_t.m - beg_t.m
}
return ""+elapsed.h+":"+elapsed.m;//so it can be used with what's above
}
/
function getH($t){
var str = $t.val();
return str.replace(/(\d{2}):(\d{2})/,"$1");
}
function getM($t){
var str = $t.val();
return str.replace(/(\d{2}:(\d{2})/,"$2");
}
EDIT 2:
If you want you can pass to the onchange EH a function pointer (therefore you can also call the function without having to trigger the event) :
function updateSum(){
var $this = $(".form-control");
var sum;
sum = doCalc($this);
$('input[name="total"]').eq(0).val(sum);
//if you put an id to the total then you can just use $(id here).val(sum)
}
therefore you can have :
$(document).ready(()=>{
updateSum();
$(".form-control").on('change', updateSum);
});
EDIT 3:
()=>{/*...*/} is just the ES6 way to declare an anonymous function, you can replace them with function(){/*...*/} if you're more comfortable with it.
EDIT 4 aka RECAP :
If you're a bit lost after this answer, here's a recap of the functions you need to add to your website :
##Regex based input processing##
function getH($t){
var str = $t.val();
return str.replace(/(\d{2}):(\d{2})/,"$1");
}
function getM($t){
var str = $t.val();
return str.replace(/(\d{2}:(\d{2})/,"$2");
}
##Calculation##
function doCalc($jq){//pass in the jqSelection that gets the two input
var $beg = $jq.eq(0);//first element with this class
var $end = $jq.eq(1);//second element with this class
var beg_t = {
h: getH($beg),
m: getM($beg)
}
var end_t = {
h: getH($end),
m: getM($end)
}
var elapsed = {
h: end_t.h - beg_t.h,
m: end_t.m - beg_t.m
}
return ""+elapsed.h+":"+elapsed.m;//so it can be used with what's above
}
##Update function##
function updateSum(){
var $this = $(".form-control");
var sum;
sum = doCalc($this);
$('input[name="total"]').eq(0).val(sum);
//if you put an id to the total then you can just use $(id here).val(sum)
}
##Event Handling and Call##
$(document).ready(function(){
updateSum();
$(".form-control").on('change', updateSum);
});

Javascript how to allow array to take more than one digit?

I've been trying lately to build up a mean calculator using html and javascript. i want to take all the inputs from the one text box add them to an array and get the average result. what i did in the following code takes only one digit because of str[i-1] is there any other alternative way of doing it? Thanks!
Output photo
function calculate()
{
var str= document.getElementById("meanvalue").value;
for(var i=0; i<str.length; i++)
{
if(str[i] == ".")
{
sum+=parseInt(str[i-1]);
count++;
}
}
sum/=count;
document.getElementById("meanresult").value=sum;
}
Here is a small example:
document.getElementById('input').onkeyup = function() {
this.value = this.value.replace(/[^0-9\.]/gi, '');// restrict non digit
var sum = 0;
var array = this.value.split(/\./);
array.forEach(function(str) {
sum += (parseInt(str, 10) || 0); //avoid NaN
});
document.getElementById('output').value = (sum / array.length || 0);// avoid NaN
}
<input type="text" id="input" />
<input type="text" id="output" readonly='' />
i just want to know how the values are updated while im typing my
inputs automatically
Here, I am using onkeyup event to handle user input.
document.getElementById('input').onkeyup = function() {
document.getElementById('output').value = this.value;//get input, set output
}
<input type="text" id="input" />
<input type="text" id="output" readonly='' />
You can use the split function on the input. I give you a quick example here :
var string = "1.3.45.7";
var array = string.split(".");
// array = [1, 3, 45, 7]
document.write(array);
First split your str and than use for loop.
var str= document.getElementById("meanvalue").value.split('.');
Also remove your if condition inside the loop.
for(var i=0; i<str.length; i++)
{
//if(str[i] == ".")
// {
sum+=parseInt(str[i-1]);`
count++;
// }
}
sum/=count;
document.getElementById("meanresult").value=sum;
hope this helps you.

How Can I Clear The Selected Field In Input Using Angularjs?

I am using MEAN stack in my application with AngularJS as my front-end. How Can I clear selected filed in input element,My Plunker
Look at my plunker for reference.
I have used Start date and End date inputs , which is used to filter the Due_date. If we select Start Date like:- 16-09-2016 the data's has filtering in the table.
In that date input has one X close button to clear the field, but which is not working, if we click that x clear button the table is showing like empty data's.
What we excatly looking for , if we click that x clear button it's should to be clear selected fileds and need to display all datas in table ....like we have given the exaple plunker is here :- http://plnkr.co/edit/QuJvCXFpKbwVd0OlkHZ2?p=preview for this plunker x clear button is working perfectly, I don't where I made a mistake,
Please help us.
My controller for daterange filter:-
.filter("myfilter", function() {
return function(items, from, to) {
var df = from;
var dt =to;
var result = [];
console.log(to);
for (var i=0; i<items.length; i++){
var date = moment(items[i].invoice_date);
date.add(items[i].terms,'d');
var tf = date;
if (date.isAfter(moment(from)) && date.isBefore(moment(to))) {
result.push(items[i]);
}
}
//console.log(items);
return result;
};
});
My html :-
<input type="date" class="form-control" name="from" ng-model="from">
<input type="date" class="form-control" name="to" ng-model="to">
Filter for daterange:-
<tr ng-repeat="data in record | myfilter:from:to">
<td> {{addDays(data.invoice_date,data.terms) | date:'yyyy-MM-dd'}}</td>
</tr>
I have created my plunker to reference :- My Plunker
Add date validation in your filter
app.filter("myfilter", function() {
return function(items, from, to) {
if(from.length!=0 && to.length!=0)
{
var df = from;
var dt =to;
var result = [];
console.log(to);
for (var i=0; i<items.length; i++){
var date = moment(items[i].invoice_date);
date.add(items[i].terms,'d');
var tf = date;
if (date.isAfter(moment(from)) && date.isBefore(moment(to))) {
result.push(items[i]);
}
}
//console.log(items);
return result;
}else
{
return items;
}
};
});
Change the filter condition to:
if (date.isAfter(moment(from)) || from == null && date.isBefore(moment(to)) || to == null)
This will remove the date constraint if from or to is not set.
Plunkr
Edit: Please add brackets like this:
if ((date.isAfter(moment(from)) || from == null) &&
(date.isBefore(moment(to)) || to == null)) {
//...
}
Updated Plunkr

getelementbyid issue with radio button

I'm trying to make an alert with the value of the selected radio button, but I allways get the first of them, regardless the one I choose...(Acompanhado);
html:
<form/>
<input type="radio" class="simple_form" name="grupo_1" value="Acompanhado" id="saida"/>
<span class="texto">Acompanhado</span>
<input type="radio" class="simple_form" name="grupo_1" value="Individual" id="saida"/>
<span class="texto">Individual</span>
</form>
js:
function save() {
var saida_js = document.getElementById('saida').value;
alert("Tipo de saida: " + saida_js);
}
Any idea ?
#Quentin: I have alot of alerts, cause Im trying to get all data from a form. I used your code, and I get no alert at all.
function save() {
var morada_js = document.getElementById('morada').value;
var data_js = document.getElementById('data').value;
var hora_js = document.getElementById('hora').value;
var radio_saida = document.getElementsByName('name_saida');
var notas_js = document.getElementById('notas').value;
var condicoes_atm_js = document.getElementById('condicoes_atm').value;
alert("Morada: " + morada_js);
alert("Data: " + data_js);
alert("Hora: " + hora_js);
function get_checked_radio(radio_saida) {
for (var i = 0; i < radio_saida.length; i++) {
var current = radio_saida[i];
if (current.checked) {
return current;
}
}
}
alert(get_checked_radio(radio_saida).value);
alert("Notas: " + notas_js);
}
An id must be unique in a document.
To find the value of a selected radio button in a group, get the group by its nameā€¦
var radios = document.getElementsByName('radio_name'); // or
var radios = document.forms.formId.elements.radio_name;
Then loop over them until you find the one with the true checked property.
function get_checked_radio(radios) {
for (var i = 0; i < radios.length; i++) {
var current = radios[i];
if (current.checked) {
return current;
}
}
}
alert(get_checked_radio(radios).value);
Makes sense because you've got two input tags with the same id saida