Creating a Dropdown list by fetching data from backend - javascript

I have created a course container and I want to populate the options by fetching them from the backend
(URL: https://ffcc-app.herokuapp.com/get/courses)
<div class="container">
<form action="#" method="POST">
<h2>Course 1</h2>
<div class="select-box">
<div class="options-container">
<select class="option" id="one">
<option value="">Select a course.. </option>
</select>
</div>
<div class="selected">
Select Courses
</div>
<div class="search-box">
<input type="text" placeholder="Search..." />
</div>
</div>
</form>
</div>
Also when I type any character in the search box it should filter the options.
Can someone help me on how to fetch the data from the URL to populate the options list?
PS: I am familiar with Fetch API for fetching the data

You could do something like this:
let result = {};
let allCourses = {};
function filterCourses() {
var filter = document.getElementById("inputFilter").value;
result.courses = allCourses.courses.filter(x => x.title.includes(filter))
let select = document.getElementById("one");
while (select.firstChild) {
select.removeChild(select.firstChild);
}
for (let i = 0; i < result.courses.length; i++){
let option = document.createElement("option");
option.value = result.courses[i]._id;
option.text = result.courses[i].title;
select.appendChild(option);
}
}
async function getCourses() {
let url = 'users.json';
try {
let res = await fetch("https://ffcc-app.herokuapp.com/get/courses");
return await res.json();
} catch (error) {
console.log(error);
}
}
async function renderCourses() {
allCourses = await getCourses();
result = Object.assign({}, allCourses);
let select = document.getElementById("one");
for (let i = 0; i < result.courses.length; i++){
let option = document.createElement("option");
option.value = result.courses[i]._id;
option.text = result.courses[i].title;
select.appendChild(option);
}
}
renderCourses()
<div class="container">
<form action="#" method="POST">
<h2>Course 1</h2>
<div class="select-box">
<div class="options-container">
<select class="option" id="one">
<option value="">Select a course.. </option>
</select>
</div>
<div class="selected">
Select Courses
</div>
<div class="search-box">
<input type="text" id="inputFilter" placeholder="Search..." onchange="filterCourses()"/>
</div>
</div>
</form>
</div>
Explanation: after loaded all the courses, I made an option for each course (with _id as option value and title as option text). This is made by function renderCourses.
Then the filterCourses function: basically it takes the value from input and looks for an option that contains what you typed in input. If you clean the input, function returns all the courses.

You have to get your api, create a function to manipulate your DOM, pass the data to this function so that it renders the content inside the select tag.
This is just for the select tag.
const select = document.querySelector('.option')
fetch('https://ffcc-app.herokuapp.com/get/courses')
.then(response => response.json())
.then(data => {
data.courses.forEach(course => render(course))
});
function render(course) {
const opt = document.createElement('option')
opt.value = course.title
const content = document.createTextNode(`${course.title}`)
opt.appendChild(content)
select.appendChild(opt)
}
<div class="container">
<form action="#" method="POST">
<h2>Course 1</h2>
<div class="select-box">
<div class="options-container">
<select class="option" id="one">
<option value="">Select a course.. </option>
</select>
</div>
<div class="selected">
Select Courses
</div>
<div class="search-box">
<input type="text" placeholder="Search..." />
</div>
</div>
</form>
</div>

Related

HTML Form Select Element Not Allowing Changes

I have a form that I am creating for my kids' school and am having issues with the drop-down list to choose the student name. The list is populated via JavaScript code, importing a student list from an associated google sheet. I added a console log for each option as they are created to show that they are in fact being created. Developer options on the link should reveal that.
Once I load the form I am unable to change the student identifier from the default option. I can't tell what I've done wrong. If I hard code the values into the HTML it works fine, but I want the teacher to be able to add and remove students via the spreadsheet because that is a more user-friendly and flexible implementation.
form.html code
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<style>
body {
background: rgb(244, 235, 234)
}
.outer-field {
border-radius: 15px;
background: white;
height: 150px;
margin: 10px;
padding: 20px;
}
.title {
padding-left: 2%;
font-weight: bold;
}
</style>
</head>
<body>
<div class="row">
<div class="col s8 offset-s2 offset-s2">
<!--Document Header-->
<div class="outer-field" style="height: 100px">
<h4>Golden Apple Reader Book Submissions</h4>
</div>
<!--Form to submit ISBN and autopopulate title and page count-->
<form id="myForm" onsubmit="event.preventDefault(); formSubmit(this) ">
<!--Creates ISBN entry field-->
<div class="outer-field">
<div class="title">Book ISBN</div>
<div class="col s8">
<div class="input-field">
<input type="text" id="ISBN" name="ISBN" class="UUID validate" form="myForm">
<label for="ISBN">ISBN</label>
</div>
</div>
<!--Creates button to check ISBN data-->
<button class="btn waves-effect waves-light" id="btn" style="margin-left: 3%" type="button" onclick="populateDetails(); return false;">Autofill Book Data From ISBN
<i class="material-icons right">send</i>
</button>
</div>
<!--Creates student name entry field-->
<div class="outer-field">
<div class="title">Student Name</div>
<div class="input-field col s12">
<select form="myForm" name="StudentID" id="StudentID" required>
<!--Add student IDs and names here-->
<!--<option value="212702">John</option>
<option value="212703">Henry</option>
<option value="003">003</option>-->
</select>
</div>
</div>
<!--Creates book title entry field-->
<div class="outer-field">
<div class="title">Book Required Information</div>
<div class="col s8">
<div class="input-field">
<input type="text" id="Title" name="Title" class="name" form="myForm" required>
<label for="Title">Book Title</label>
</div>
</div>
<!--Creates book page count entry field-->
<div class="col s4">
<div class="input-field">
<input type="number" id="PageCount" name="PageCount" class="pages" form="myForm" required>
<label for="PageCount">Book Page Count</label>
</div>
</div>
</div>
<!--Creates button to submit data-->
<button class="btn waves-effect waves-light" type="submit" name="action" style="margin-left: 3%" >Submit
<i class="material-icons right">send</i>
</button>
</form>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<script>
M.FormSelect.init(document.querySelectorAll('select'));
//function to populate student list element
(function () {
google.script.run.withSuccessHandler(
function (selectList) {
var select = document.getElementById('StudentID');
for( var i=0; i<selectList.length; i++ ) {
//initial attempt commented here for troubleshooting
//var option = document.createElement('option');
//option.value = selectList[i][0];
//option.text = selectList[i][4];
var option = new Option(selectList[i][4], selectList[i][0]);
console.log(option);
select.add(option, undefined);
}
console.log(select)
}
).getSelectList();
}());
//Uses the ISBN to populate the book title and page quantity
function populateDetails(){
isbn=document.getElementById('ISBN').value;
//isbn=9781492680550;//for debugging only
var url = "https://www.googleapis.com/books/v1/volumes?country=US&q=isbn:" + isbn;
var obj
var title="No Entry Identified";
var pageCount=0;
var titleout=document.getElementById('Title');
var pageout=document.getElementById('PageCount');
//fetches URL data from google books API
fetch(url)
.then(res => res.json())
.then(data => obj = data)
.then(
function(settitle){
//Assigns title to variable and text field
title = obj.items[0].volumeInfo.title
titleout.value=title;
titleout.focus();
},
function(titlerror){
})
.then(
function(setpages){
//Assigns page count to variable and text field
pageCount = obj.items[0].volumeInfo.pageCount
pageout.value=pageCount;
pageout.focus();
},
function(pageerror){
})
//In the case that no entry is found in google books API, assigns default values to text fields and deconflicts the overlapping label and value fields
titleout.value=title;
titleout.focus();
pageout.value=pageCount;
pageout.focus();
}
//Submits form data to spreadsheet
function formSubmit (data) {
var dataToSubmit = {
studentID: data.StudentID.value,
title: data.Title.value,
pageCount: data.PageCount.value
}
//Provides a success message to the user
google.script.run.withSuccessHandler(function () {
myForm.reset()
M.toast({html: "Thank you! You have successfully submitted!"})
}).submitData(dataToSubmit)
}
</script>
</body>
</html>
code.gs code
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Submissions")
var ss2= SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Students")
var last=ss2.getLastRow();
var students=ss2.getRange(2,1,last-1,5).getValues();
function getSelectList() {
try {
return students;
}
catch(err) {
Logger.log(err);
}
}
function doGet() {
return HtmlService.createTemplateFromFile('form').evaluate().addMetaTag('viewport', 'width=device-width, initial-scale=1')
}
function submitData (data) {
ss.appendRow([new Date(),data.studentID, data.title, data.pageCount])
}
spreadsheet content:
Student ID Number
Student Name
Teacher Name
Grade
Concatenation
UNK1
John
TeacherA
K
Grade: K, Teacher: TeacherA, Name: John
UNK2
Henry
TeacherA
K
Grade: K, Teacher: TeacherA, Name: Henry
UNK3
Paige
TeacherA
K
Grade: K, Teacher: TeacherA, Name: Paige
UNK4
Raelyn
TeacherA
K
Grade: K, Teacher: TeacherA, Name: Raelyn
UNK5
Danielle
TeacherA
K
Grade: K, Teacher: TeacherA, Name: Danielle
UNK6
Olivia
TeacherA
K
Grade: K, Teacher: TeacherA, Name: Olivia
When I saw your script, I thought that there is a modification point. Please modify as follows.
From:
M.FormSelect.init(document.querySelectorAll('select'));
//function to populate student list element
(function () {
google.script.run.withSuccessHandler(
function (selectList) {
var select = document.getElementById('StudentID');
for( var i=0; i<selectList.length; i++ ) {
//initial attempt commented here for troubleshooting
//var option = document.createElement('option');
//option.value = selectList[i][0];
//option.text = selectList[i][4];
var option = new Option(selectList[i][4], selectList[i][0]);
console.log(option);
select.add(option, undefined);
}
console.log(select)
}
).getSelectList();
}());
To:
//function to populate student list element
(function () {
google.script.run.withSuccessHandler(
function (selectList) {
var select = document.getElementById('StudentID');
for( var i=0; i<selectList.length; i++ ) {
//initial attempt commented here for troubleshooting
//var option = document.createElement('option');
//option.value = selectList[i][0];
//option.text = selectList[i][4];
var option = new Option(selectList[i][4], selectList[i][0]);
console.log(option);
select.add(option, undefined);
}
console.log(select)
M.FormSelect.init(document.querySelectorAll('select')); // Moved.
}
).getSelectList();
}());
In this modification, M.FormSelect.init(document.querySelectorAll('select')) was moved.
I thought that (function () { and }()); might be not required to be used.

How to hide div based on select the dropdown in angular js

How to hide div based on select the dropdown.
Here is the sample code I have written
<div>
<p>Course Type</p>
<div>
<select name="student-type" id="student-type" class="icon-select-down" ng-model="studentType" ng-change="getOption(this)">
<option value="java" selected>Java</option>
<option value="angularjs">Angular js</option>
<option value="reactJs">React js</option>
</select>
</div>
</div>
<div ng-if="studentType">
<p>Attendence Days</p>
<div class="slice-item">
<input type="text" class="input input-text" ng-model="attendenceDays" required validate-on="blur" ng-pattern="/^([1-9]|10)$/" invalid-message="'You must enter number between 1 to 25'" />
</div>
</div>
In controller i have written below code.
$scope.getOption = function(value) {
if (value.studentType = "angularjs") {
$scope.studentType = "false";
}
};
Can any one please guide me solving this problem?
What is the issue with your code?
Its purely the logical issue. You are checking ng-if="studentType" for showing the input container. Inside the change event you are using if (value.studentType = "angularjs"). This is not a condition checking, its assignment opertator. You have to use if (value.studentType == "angularjs") or if (value.studentType === "angularjs") to compare the value value.studentType with string "angularjs". In your scenario, the if statement will always assign "angularjs" to studentType and after that the code inside if will assign "false" to studentType. There is no need to do this in this way.
You could do this in multiple ways. I suggest two options here
Option 1: Inside the template check the value for studentType. If studentType is not angularjs then only display the input. So just add a condition in ng-if="studentType !== 'angularjs'". Here you dont have to write any logic inside the controller
Working Fiddle
var app = angular.module('myApp', []);
app.controller('myCtrl', function ($scope) {
// $scope.showInput = true;
// $scope.getOption = function (value) {
// if (value.studentType == "angularjs") {
// $scope.showInput = false;
// }
// };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<div>
<p>Course Type</p>
<div>
<select name="student-type" id="student-type" class="icon-select-down" ng-model="studentType"
ng-change="getOption(this)">
<option value="java" selected>Java</option>
<option value="angularjs">Angular js</option>
<option value="reactJs">React js</option>
</select>
</div>
</div>
<div ng-if="studentType !== 'angularjs'">
<p>Attendence Days</p>
<div class="slice-item">
<input type="text" class="input input-text" ng-model="attendenceDays" required validate-on="blur"
ng-pattern="/^([1-9]|10)$/" invalid-message="'You must enter number between 1 to 25'" />
</div>
</div>
</div>
Option 2: Inside the change function, check the value of selected option. Set a visiblity boolean based on the value of selected option. Make the input visible based on that boolean
Working Fiddle
var app = angular.module('myApp', []);
app.controller('myCtrl', function ($scope) {
$scope.showInput = true;
$scope.getOption = function (value) {
$scope.showInput = value.studentType !== "angularjs";
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<div>
<p>Course Type</p>
<div>
<select name="student-type" id="student-type" class="icon-select-down" ng-model="studentType"
ng-change="getOption(this)">
<option value="java" selected>Java</option>
<option value="angularjs">Angular js</option>
<option value="reactJs">React js</option>
</select>
</div>
</div>
<div ng-if="showInput">
<p>Attendence Days</p>
<div class="slice-item">
<input type="text" class="input input-text" ng-model="attendenceDays" required validate-on="blur"
ng-pattern="/^([1-9]|10)$/" invalid-message="'You must enter number between 1 to 25'" />
</div>
</div>
</div>

How can I give a foreach through the data-index JavaScript

I'm trying to give a for or foreach based on my data-index to add value to each of the adesaoTest fields
If the data-index is equal to zero it normally goes through the process
The first time the code is compiled normally, but the second time when the data-index is = 1 it does not calculate
JavaScript
adesao = 0.00;
const totalAdesao = document.querySelectorAll('.quota-row');
totalAdesao.forEach(adesaoTest => {
var index = adesaoTest.getAttribute('data-index');
var entrada = document.getElementById(`quota-entrada-${index}`);
var parcelas = document.getElementById(`quota-parcelas-${index}`);
var adesaoTest = document.getElementById(`quota-adesao-${index}`);
adesao = parseFloat(entrada.value) / parcelas.value;
adesaoTest.value = adesao;
})
For each of the fields var adesaoTest = document.getElementById(quota-adesao-${index})
must perform calculation above
Note:
I'm using fetch to add the new entries that will go through for or foreach
When the second element is created it gives the following error
This is the function that adds the other elements
var quotasDiv = document.getElementById('quotas');
const id = quotasDiv.querySelectorAll('.row').length + 1;
var quotaPrincipal = document.getElementById('quota-principal');
const request = new Request('/configuracoes/listFormaPagamento/json', { method: 'POST' });
fetch(request)
.then(res => {
res.json()
.then(data => {
var html = `<div class="row quota-row" data-index="${id}">
<div class="col-8" id="quota-${id}" >
<div>
<div class="col-xs-2">
<span>Entrada ${(id + 1)}</span>
<input onblur="calculaRestante(this)" type="text" data-index="${id}" id="quota-entrada-${id}" required="" name="entrada[]" placeholder="Primeira Parte" id="valor8" value="0">
</div>
<div class="col-xs-2 dateInput">
<span>Forma de Pagamento</span>
<select onchange="onChangeFormaPagamento(this)" data-index="${id}" id="quota-forma-pagamento-${id}" name="forma_pagamento[]">
<option value="">Selecione a forma de pagamento</option>
${data.map(forma_pagamento => {
return `<option value="${forma_pagamento.id_formas_pagamento}"> ${forma_pagamento.forma_pagamento} </option>`
})}
</select>
</div>
<div class="col-xs-1 dateInput">
<span>Parcelas</span>
<select data-index="${id}" id="quota-parcelas-${id}" onchange="calculaAdesao()" name="parcelas[]" >
<option value=""></option>
</select>
</div>
<div class="col-xs-2">
<span>Vencimento</span>
<input data-index="${id}" type="date" required="" id="quota-vencimento-${id}" name="vencimento[]" placeholder="Entrada">
</div>
<div class="col-xs-2">
<span>Adesão</span>
<input data-index="${id}" type="text" required="" id="quota-adesao-${id} "name="adesao[]" placeholder="Valor de entrada" id="valor6">
</div>
<div class="col-xs-2">
<span style="color: red; cursor: pointer; margin-top: 3rem" onclick="deleteQuotaHtml(this)"><i class="fas fa-trash-alt"></i></span>
<div>
</div>
</div>
</div>`;
quotasDiv.innerHTML += html;
})
})
}

How to Pass id and name from the first form, and Show only the name in second form in angularjs

I Have two forms.In these forms am getting input from the first form and show that in the second form, Which means if the user selected the currency from the dropdown, i need to pass id and the the currency name. But show only the currency name in the second form. I tried one method (dont know whether it is correct or not) it is showing the id only. am new to angular. is there anyway to solve this?
HTML
<div class="row text-center" ng-show="firstform">
<form name="validation">
<label>Currency</label>
<select ng-model="CurrencyId" ng-selected="CurrencyId" class="form-control" id="CurrencyId">
<option ng:repeat="CurrencyId in currencyList" ng-selected="selectedCurrencyType == CurrencyId.id" value={{CurrencyId.currencyId}}>{{CurrencyId.name}}</option>
</select>
<label>Grade</label>
<select ng-model="GradeId" ng-selected="GradeId" class="form-control" id="GradeId">
<option ng:repeat="GradeId in RaceGradeList" ng-selected="selectedGrade == GradeId.id" value={{GradeId.id}}>{{GradeId.gradeName}}</option>
</select>
<button type="submit"value="add" ng-click="savedetails()" />
</form>
</div>
<div class="row text-center" ng-show="secondform">
<form name="thirdform">
<ul >
<li><p>Currency:{{CurrencyId}}</p> </li>
<li><p>Grade:{{GradeId}}</p> </li>
</ul>
</form>
</div>
angular controller
$scope.savedetails = function () {
$scope.firstform= false;
$scope.secondform = true;
}
This is the most simplest solution that you can go for. Instead of having the value={{CurrencyId.currencyId}} set it as value={{CurrencyId.name}} for the options in the dropdown and you are good to go. Below is the demo for the same. But if you want to save currencyId as the value then you will have to iterate over the array and find the name based on the selected currencyId and then show that in the view.
UPDATE
Updated the code to have the currencyId being stored as the selected value and then based on that showing the name in the view.
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.currencyList = [{
currencyId: 1,
name: "INR"
},
{
currencyId: 2,
name: "$"
},
{
currencyId: 3,
name: "#"
}
];
$scope.currencyChanged = function() {
var selectedCurrency;
for (var i = 0; i < $scope.currencyList.length; i++) {
var thisCurr = $scope.currencyList[i];
if ($scope.CurrencyId == thisCurr.currencyId)
selectedCurrency = thisCurr.name;
}
return selectedCurrency;
}
$scope.firstform = true;
$scope.savedetails = function() {
$scope.firstform = false;
$scope.secondform = true;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp" ng-controller="myCtrl">
<div class="row text-center" ng-show="firstform">
<form name="validation">
<label>Currency</label>
<select ng-model="CurrencyId" ng-selected="CurrencyId" class="form-control" id="CurrencyId">
<option ng:repeat="CurrencyId in currencyList" ng-selected="CurrencyId == CurrencyId.currencyId" value={{CurrencyId.currencyId}}>{{CurrencyId.name}}</option>
</select>
<button type="button" value="add" ng-click="savedetails()">Save Details</button>
</form>
</div>
<div class="row text-center" ng-show="secondform">
<form name="thirdform">
<ul>
<li>
<p>Currency:{{currencyChanged()}}</p>
</li>
</ul>
</form>
</div>
</body>
Hope it helps :)
You can use ng-options , its very flexiable where we can display one value and select either entire object or any specific property.
Please check below plunker , hope it meets your requirement
https://plnkr.co/edit/JQjmAwk62R8rfAlTZ696?p=preview
<select ng-model="CurrencyId" ng-options="currency.id for currency in currencyList" class="form-control" id="CurrencyId" >
</select>
For more details on ng-options , go through below video
https://www.youtube.com/watch?v=vqx3zCy4d3I
try
<li><p>Currency:{{CurrencyId.name}</p> </li>

How to clear old value from checkbox before next try?

I wrote my JavaScript code to get a value with JSON function to show in a checkbox, but every time I try with new options the old values still exist in the check box. I want to clear the checkbox before the next try. I marked the problem area in the code below:
HTML:
<div class="panel-body">
<div class="form-group">
<label for="field-1" class="col-sm-3 control-label" >Select Group</label>
<div class="col-md-2">
<select class="form-control" name="perms" onchange="OnSelectionChange(this)">
<option>Choice your group</option>
{foreach $perms as $perm}
<option value="{$perm.pID}">{$perm.title}</option>
{/foreach}
</select>
</div>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-12">
<strong>Edite Permisions:</strong>
<br />
<br />
</div>
<div class="col-sm-6" style="width:100%;">
<ul class="icheck-list">
{foreach $rps as $rp}
<li>
<input type="checkbox" name="updatePERM[]" id="{$rp.id}" value="{$rp.id}">
<label style="padding-left: 5px;vertical-align: middle;" >{$rp.rname}</label> <pre>{$rp.rdes}</pre>
</li>
{/foreach}
</ul>
</div>
</div>
</div>
</div>
JS:
function OnSelectionChange (select) {
var selectedOption = select.options[select.selectedIndex];
var url = "./include/getPerms.php?key="+selectedOption.value+"";
$.getJSON(url, function(data) {
$.each(data.rules, function(i, rule) {
// MY PROBLEM LINE: HOW I CAN DO THIS ?
if input:checkbox.val() != rule.id => set attr('checked', false)
else if input:checkbox.val() == rule.id => set attr('checked', true)
// HOW I CAN DO THIS ?
});
});
}
function OnSelectionChange(select) {
var selectedOption = select.options[select.selectedIndex];
var url = "./include/getPerms.php?key=" + selectedOption.value + "";
$.getJSON(url, function (data) {
// Default make all checkbox un-checked.
$("input:checkbox").prop("checked", false)
$.each(data.rules, function (i, rule) {
// If rule.id matches with the checkbox values then make those checkbox checked
$(":checkbox[value="+rule.id+"]").prop("checked",true);
});
});

Categories