How to change name attributes for auto added inputs and textareas? - html

I'm trying to create a cv creater form and need to let users add more inputs (auto).
I created inputs and they work just fine, but I need to change the name attribute for each auto added block.
For example :
<input type="text" id="fname" name="fname">
<input type="text" id="fname" name="fname2">
<input type="text" id="fname" name="fname3">
I know I can use name="value[]" array, but every new block goes into a different column in the database, so I need to change attributes.
My code :
$(document).ready(function() {
var max_fields = 10;
var wrapper = $("#contant");
var add_button = $("#add_form_field");
var x = 1;
$(add_button).click(function(e) {
e.preventDefault();
if (x < max_fields) {
x++;
$(wrapper).append('<div id="input-social" class="input-container"><input type="text" id="social" class="col-11 form-control" name="fname" placeholder="fname"> <span id="deleteInput" class="AutoInput" title="Delete"><i class="fas fa-trash-alt"></i></span></div>');
} else {
alert('You Riched limit.')
}
});
$(wrapper).on("click", "#deleteInput", function(e) {
e.preventDefault();
$(this).parent('#input-social').remove();
x--;
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://kit.fontawesome.com/e794a0f8b4.js" crossorigin="anonymous"></script>
<div class="form-group">
<div class="row">
<label class="col-3 inputFontSize" for="social">Others</label>
<div id="contant" class="col-7">
<button id="add_form_field" class="btn add_form_field">Add more <i class="fas fa-plus"></i></button>
</div>
<!-- col-9 -->
</div>
<!-- row -->
</div>
<!-- form-group -->
Thanks for all helps

You can use your x variable that is incremented for each added input and append it to the name attribute. We'll use a 'template string'. The adjustment is name="fname${x}" which will substitute ${x} for the value of x.
$(wrapper).append(`
<div id="input-social" class="input-container">
<input type="text" id="social" class="col-11 form-control" name="fname${x}" placeholder="fname">
<span id="deleteInput" class="AutoInput" title="Delete">
<i class="fas fa-trash-alt"></i>
</span>
</div>`
);
$(document).ready(function() {
var max_fields = 10;
var wrapper = $("#contant");
var add_button = $("#add_form_field");
var x = 1;
$(add_button).click(function(e) {
e.preventDefault();
if (x < max_fields) {
x++;
$(wrapper).append(`<div id="input-social" class="input-container"><input type="text" id="social" class="col-11 form-control" name="fname${x}" placeholder="fname"> <span id="deleteInput" class="AutoInput" title="Delete"><i class="fas fa-trash-alt"></i></span></div>`);
} else {
alert('You Riched limit.')
}
});
$(wrapper).on("click", "#deleteInput", function(e) {
e.preventDefault();
$(this).parent('#input-social').remove();
x--;
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://kit.fontawesome.com/e794a0f8b4.js" crossorigin="anonymous"></script>
<div class="form-group">
<div class="row">
<label class="col-3 inputFontSize" for="social">Others</label>
<div id="contant" class="col-7">
<button id="add_form_field" class="btn add_form_field">Add more <i class="fas fa-plus"></i></button>
</div>
<!-- col-9 -->
</div>
<!-- row -->
</div>
<!-- form-group -->

Related

how to fix jQuery 'previous' button

The code below shows a multi step form, the second page displays two buttons next and previous and for some reason the previous button doesn't work. I tried playing with code a lot but I couldn't figure it out. Please help.
<form class="form-wrapper">
<fieldset class="section is-active">
<h3>Details</h3>
<div class="inputlabel">
<label>Exchange</label>
</div>
<input type="text" placeholder="Exchange..">
<div class="button">Next</div>
</fieldset>
<fieldset class="section">
<h3>Title</h3>
<div class="inputlabel">
<label>Balance</label>
</div>
<input type="text" placeholder="Password" readonly>
<div class="btnpre" onclick="prvbtn()" id="btnprevious">Previous</div>
<input class="submit button" type="submit" value="Finish">
</fieldset>
<fieldset class="section">
<i class="fas fa-check-circle fa-7x"></i>
<h2>Saved</h2>
<p>Your Data has been saved</p>
<div class="button" id="button2">Close</div>
</fieldset>
</form>
This is the jQuery script
<script>
$(document).ready(function(){
$(".form-wrapper .button").click(function(){
var button = $(this);
var currentSection = button.parents(".section");
var currentSectionIndex = currentSection.index();
var headerSection = $('.steps li').eq(currentSectionIndex);
currentSection.removeClass("is-active").next().addClass("is-active");
headerSection.removeClass("is-active").next().addClass("is-active");
$(".form-wrapper").submit(function(e) {
e.preventDefault();
});
function prvbtn(){
if(currentSectionIndex === 1){
currentSectionIndex = 0;
}
if(currentSectionIndex === 2){
$(document).find(".form-wrapper .section").first().addClass("is-active");
$(document).find(".steps li").first().addClass("is-active");
}
});
});
</script>
Consider the following example.
$(function() {
// Define a Global Index
var sectionIndex = 0;
$(".form-wrapper .button").click(function() {
// Examine the button and determine which button was clicked
if ($(this).hasClass("next")) {
// Use the current Index and them increment it
$(".section").eq(sectionIndex++).toggleClass("is-active");
$(".section").eq(sectionIndex).toggleClass("is-active");
} else {
// Use the current Index and them decrement it
$(".section").eq(sectionIndex--).toggleClass("is-active");
$(".section").eq(sectionIndex).toggleClass("is-active");
}
});
$(".form-wrapper").submit(function(e) {
e.preventDefault();
});
});
.section {
display: none;
}
.section.is-active {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form class="form-wrapper">
<fieldset class="section is-active">
<h3>Details</h3>
<div class="inputlabel">
<label>Exchange</label>
</div>
<input type="text" placeholder="Exchange..">
<div class="next button">Next</div>
</fieldset>
<fieldset class="section">
<h3>Title</h3>
<div class="inputlabel">
<label>Balance</label>
</div>
<input type="text" placeholder="Password" readonly>
<div class="previous button" id="btnprevious">Previous</div>
<input class="submit button" type="submit" value="Finish">
</fieldset>
<fieldset class="section">
<i class="fas fa-check-circle fa-7x"></i>
<h2>Saved</h2>
<p>Your Data has been saved</p>
<div class="button" id="button2">Close</div>
</fieldset>
</form>
This assigns one callback to all button elements. With an if statement, we can easily determine the direction.

Error TypeError: Cannot read property 'fn' of undefined userClicked # funcs.gs:8

I have made an web app using google script connected to spreadsheet.
all was running well till i tried to put a functionality of sending email notification when user submits a form information
see error code when run log of user clicked function-
TypeError: Cannot read property 'fn' of undefined userClicked #funcs.gs:8
function-js page is below
'function userClicked(userInfo) {
var ss = SpreadsheetApp.openByUrl(url1);
var ws = ss.getSheetByName("SNAGS");
ws.appendRow([userInfo.fn,
userInfo.contact,
userInfo.email,
userInfo.house,
userInfo.snag,
userInfo.query,
new Date()]);
<script>
document.addEventListener('DOMContentLoaded', function()
{
document.getElementById("btn").addEventListener("click",doStuff);
document.getElementById("house").addEventListener("input",getInfo);
var selectBoxes = document.querySelectorAll('select');
M.FormSelect.init(selectBoxes);
google.script.run.withSuccessHandler(populateHouse).getHouse();
}
);
function populateHouse(hous)
{
var autocomplete = document.getElementById('house');
var instances = M.Autocomplete.init(autocomplete, { data: hous });
}
function doStuff()
{
var isValid = document.getElementById("fn").checkValidity();
if(!isValid)
{
M.toast({html: 'Name Required!'});
}
else
{
addRecord();
}
}
function addRecord ()
{
var userInfo = {};
userInfo.fn = document.getElementById("fn").value;
userInfo.contact = document.getElementById("contact").value;
userInfo.email = document.getElementById("email").value;
userInfo.house = document.getElementById("house").value;
userInfo.snag = document.getElementById("snag").value;
userInfo.query = document.getElementById("query").value;
google.script.run.userClicked(userInfo);
document.getElementById("fn").value ="";
document.getElementById("contact").value ="";
document.getElementById("email").value ="";
document.getElementById("house").value ="";
document.getElementById("snag").value ="";
document.getElementById("query").value ="";
M.updateTextFields();
var myApp = document.getElementById("snag");
myApp.selectedIindex = 0;
M.FormSelect.init(myApp);
}
function getInfo ()
{
var HouseInfo = document.getElementById("house").value;
if(HouseInfo.length === 3)
{
google.script.run.withSucceshandler(updateInfo).getData(HouseInfo);
}
}
function updateInfo (infos)
{
document.getElementById("info").value = infos;
M.updateTextFields();
}
</script>
<!DOCTYPE html>
<html>
<head>
<base target="_self">
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<?!= include("page-css"); ?>
</head>
<body>
<div class="container">
<h3>TPM Maintance |Ticketing System</h3>
<br>
<div class="row">
<div class="input-field col s4">
<input placeholder="Your Full Names" id="fn" type="text" class="validate" required >
<label for="fn">Your Name:</label>
</div>
<div class="input-field col s4">
<input id="contact" type="text" class="validate">
<label for="contact"> Your Phone number:</label>
</div>
<div class="input-field col s4">
<input id="email" type="email" class="validate" required>
<label for="email">Email:</label>
</div>
</div>
<div class="row">
<div class="input-field col s4">
<i class="material-icons prefix">home</i>
<input type="text" id="house" class="autocomplete" required>
<label for="house">Location Area/ House Unit# </label>
</div>
<div class="input-field col s4">
<select id="snag" required>
<option disabled selected> Snag Category</option>
<?!= list; ?>
</select>
<label>Snag Type</label>
</div>
<div class="input-field col s4">
<input disabled id="info" type="text" class="validate">
<label for="info">Unit_Info</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<textarea id="query" class="materialize-textarea"></textarea>
<label for="query">Query Desc:</label>
</div>
</div>
<div class="row">
<button id="btn" class="btn waves-effect waves-light deep-orange darken-2" type="submit" name="action">Send Ticket!
<i class="material-icons right">send</i>
</button>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<?!= include("page-js"); ?>
</body>
</html>
//html part
please see more code from my work thanks. please excuse me im abit a newbie
If you are running the steps from the tutorial video you have tried to run userClicked() function to authorize the Gmail API's. Since Apps Script is thinking that it's a standalone function, userInfo is considered undefined. This is expected behavior.
Excerpt from video:

Add CSS Class to Row Elements If Value Equals

Using JQuery I would like to check the value of an input, if it equals Complete I would like to add the Bootstrap class is-valid to that input, and all the other inputs on the same row.
Something like this (pseudo code);
if wb_status_reg = Complete {
// add is-valid to all row inputs / select boxes
}
I should note that sometimes the row will contain a select box, not just text inputs. Also, I'm unable to edit the html as it's being generated by a form builder component (in a CMS).
My code is currently working but I know it's too long and could be improved. In my code i'm showing one form-row but I actually have many more, so I need to duplicate this a few more times.
How can I achieve this in a more efficient way?
jQuery(document).ready(function($) {
var wb_stage_reg = $('#wb_stage_reg');
var wb_status_reg = $('#wb_status_reg');
var wb_date_reg = $('#wb_date_reg');
setIsValid($);
});
function setIsValid($) {
wb_stage_reg = ($(wb_status_reg).val().trim() == "Complete") ? $(wb_stage_reg).addClass("is-valid") : "";
wb_status_reg = ($(wb_status_reg).val().trim() == "Complete") ? $(wb_status_reg).addClass("is-valid") : "";
wb_date_reg = ($(wb_status_reg).val().trim() == "Complete") ? $(wb_date_reg).addClass("is-valid") : "";
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="form-row">
<div class="col-3">
<div class="form-group rsform-block-wb-stage-reg">
<div class="formControls">
<div class="sp-input-wrap">
<input class="form-control" id="wb_stage_reg" name="form[wb_stage_reg]" type="text" value="Registration"><span></span>
</div>
</div>
</div>
</div>
<div class="col-3">
<div class="form-group rsform-block-wb-status-reg">
<div class="formControls">
<div class="sp-input-wrap">
<input class="form-control" id="wb_status_reg" name="form[wb_status_reg]" type="text" value="Complete"><span></span>
</div>
</div>
</div>
</div>
<div class="col-3">
<div class="form-group rsform-block-wb-date-reg">
<div class="formControls">
<div class="sp-input-wrap">
<input class="form-control" id="wb_date_reg" name="form[wb_date_reg]" type="text" value="2020-06-08 09:41:40"><span></span>
</div>
</div>
</div>
</div>
</div>
Something like this:
You need to change ID to class on all fields
Since you cannot, I use the name instead:
$(function() {
$("[name='form[wb_status_reg]']").each(function() {
const $parent = $(this).closest(".form-row");
const complete = this.value === "Complete";
$parent.find("[name='form[wb_date_reg]'], [name='form[wb_stage_reg]']").toggleClass("is-valid",complete)
})
});
.is-valid { color:green}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="form-row">
<div class="col-3">
<div class="form-group rsform-block-wb-stage-reg">
<div class="formControls">
<div class="sp-input-wrap">
<input class="form-control wb_stage_reg" name="form[wb_stage_reg]" type="text" value="Registration"><span></span>
</div>
</div>
</div>
</div>
<div class="col-3">
<div class="form-group rsform-block-wb-status-reg">
<div class="formControls">
<div class="sp-input-wrap">
<input class="form-control wb_status_reg" name="form[wb_status_reg]" type="text" value="Complete"><span></span>
</div>
</div>
</div>
</div>
<div class="col-3">
<div class="form-group rsform-block-wb-date-reg">
<div class="formControls">
<div class="sp-input-wrap">
<input class="form-control wb_date_reg" name="form[wb_date_reg]" type="text" value="2020-06-08 09:41:40"><span></span>
</div>
</div>
</div>
</div>
</div>

Ng-class with condition in AngularJS

I have the below popup where the user can encode item information.
My requirement is that, when Foreign Currency and Conversion Rate are both have values, it should multiply Foreign Currency * Conversion Rate to get the Amount. And when both Foreign Currency and Conversion Rate are 0, then Amount field should accept user input.
Currently, I have the below HTML.
<div class="form-group" show-errors>
<label for="foreignCurrency" class="control-label col-md-3 text-muted">Foreign Currency</label>
<div class="col-md-9">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-dollar fa-lg"></i> </span>
<input type="number" id="foreignCurrency" name="foreignCurrency" class="form-control" placeholder="Foreign Currency" ng-model="vm.newItem.newItemEnt.ForeignCurrency" value="{{vm.newItem.newItemEnt.ForeignCurrency || 0}}" min="0" />
</div>
<p class="help-block" ng-if="perksFrm.foreignCurrency.$error.min">The minimum foreign currency value is 0</p>
</div>
<div class="form-group" show-errors>
<label for="convRate" class="control-label col-md-3 text-muted">Conversion Rate</label>
<div class="col-md-9">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-money"></i></span>
<input type="number" id="convRate" name="convRate" class="form-control" placeholder="Conversion Rate" ng-model="vm.newItem.newItemEnt.ConversionRate" ng-required="vm.newItem.newItemEnt.ForeignCurrency" value="{{vm.newItem.newItemEnt.ConversionRate || 0}}" min="0" />
</div>
<p class="help-block" ng-if="perksFrm.convRate.$error.required">The conversion rate is required</p>
<p class="help-block" ng-if="perksFrm.convRate.$error.min">The minimum conversion rate is 0</p>
</div>
<div class="form-group" show-errors>
<label for="amount" class="control-label col-md-3 text-muted">Amount</label>
<div class="col-md-9">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-money"></i></span>
<input type="number" id="amount" name="amount" class="form-control" placeholder="Amount" ng-model="vm.newItem.newItemEnt.Amount" required />
</div>
<p class="help-block" ng-if="perksFrm.amount.$error.required">The first name is required</p>
</div>
In Amount html, I can do it like this {{vm.newItem.newItemEnt.ForeignCurrency * vm.newItem.newItemEnt.ConversionRate}}. But, what if they have a 0 value and my requirement is to accept the user input from Amount textbox.
Any advise to achieve my requirements?
TIA
According to your requirment, I tried to provide you answer.
Please find Code for this, also JS fiddle demo.
HTML
<style>
.error{
border-color:red;
}
</style>
<div ng-app="myApp" ng-controller="myCtrl">
<div class="row">
<div class="col-lg-2">Foreign Currency</div>
<div class="col-lg-2"><input type="number" ng-model="FCurrency" /></div>
</div>
<div class="row">
<div class="col-lg-2">Rate</div>
<div class="col-lg-2"><input type="number" ng-model="Rate" /></div>
</div>
<div class="row">
<div class="col-lg-2">Amount</div>
<div class="col-lg-2"><input ng-class="{error : RateAmount <= 0}" ng-disabled="isAmountDisable"
type="number" ng-model="RateAmount" /></div>
</div>
</div>
JS
var myApp = angular.module("myApp", []);
myApp.controller('myCtrl', function ($scope) {
$scope.RateAmount = 0;
$scope.isAmountDisable = false;
function setRateAmount() {
if ($scope.FCurrency > 0 && $scope.Rate > 0) {
$scope.RateAmount = ($scope.FCurrency * $scope.Rate);
$scope.isAmountDisable = true;
}
else {
$scope.RateAmount = 0;
$scope.isAmountDisable = false;
}
}
$scope.$watch('FCurrency', function (newval, oldval) {
setRateAmount();
});
$scope.$watch('Rate', function (newval, oldval) {
setRateAmount();
});
});
JS Fiddle Demo
Did you tried to use ng-change on foreignCurrency and convRate input.
when those input change you can calcul your amount value and disable it.
if they are both 0, you can enable it.
Something like this :
function change() {
var foreignCurrency = vm.newItem.newItemEnt.ForeignCurrency;
var conversionRate = vm.newItem.newItemEnt.ConversionRate;
if (foreignCurrency === 0 && conversionRate === 0) {
vm.enableAmout = true;
} else {
vm.enableAmout = false;
vm.vm.newItem.newItemEnt.Amount = foreignCurrency * conversionRate;
}
}

knockout does not change the radio button view

I have a working panel with radio buttons a label and a textfield. Everything works good except if i click on radio buttons explicitly the radio button does not change the radio button view.
Here the plnkr link to it:
https://embed.plnkr.co/auD0sMEL88EsuaQqvt7E/
As #user3297291 mention that the checked and click binding get in confict.
Add this binding:
ko.bindingHandlers.stopBubble = {
init: function(element) {
ko.utils.registerEventHandler(element, "click", function(event) {
event.cancelBubble = true;
if (event.stopPropagation) {
event.stopPropagation();
}
});
}
};
You have to add in every radio element this binding like this:
<input data-bind="checked: discountValue, stopBubble: true" id="discountArbitrary" name="discount" type="radio" value="arbitrary" />
I created one jsfiddle that works as you expected.
https://jsfiddle.net/astrapi69/s3r60uLu/
I guess the click binding is conflicting with checked binding.
You can use computeds to calculate enabled/focused flags.
You can check modified code (I've omitted focused flags in favor of simplicity):
// Code goes here
var DiscountViewModel = function() {
var self = this;
self.arbitrary = ko.observable();
self.percent = ko.observable();
self.permanent = ko.observable();
self.discountValue = ko.observable('arbitrary');
self.enableArbitrary = ko.computed(() => self.discountValue() === 'arbitrary');
self.enablePercent = ko.computed(() => self.discountValue() === 'percent');
self.enablePermanent = ko.computed(() => self.discountValue() === 'permanent');
self.onArbitrary = onArbitrary;
self.onPercent = onPercent;
self.onPermanent = onPermanent;
function onArbitrary() {
self.discountValue('arbitrary');
}
function onPercent() {
self.discountValue('percent');
}
function onPermanent() {
self.discountValue('permanent');
}
};
var vm = new DiscountViewModel();
ko.applyBindings(vm);
/* Styles go here */
.header-line {
margin-bottom:20px;
margin-top:20px;
margin-left:20px;
}
<script data-require="jquery#2.1.3" data-semver="2.1.3" src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.3.3/js/tether.js"></script>
<link data-require="bootstrap#4.0.0-alpha.2" data-semver="4.0.0-alpha.2" rel="stylesheet" href="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/css/bootstrap.css" />
<script data-require="bootstrap#4.0.0-alpha.2" data-semver="4.0.0-alpha.2" src="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/js/bootstrap.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-debug.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js" type="text/javascript" defer="defer"></script>
<h1 class="header-line">
KO binding hasFocus over boolean values
</h1>
<div class="form-group row">
<div class="col-xs-1">
</div>
<div class="col-xs-1">
<input name="discount" type="radio" value="arbitrary" data-bind="checked: discountValue" />
</div>
<div class="col-xs-4">
<label for="arbitrary" data-bind="click: onArbitrary">Discount arbitrary</label>
</div>
<div class="col-xs-5">
<input type="text" class="form-control" id="arbitrary" placeholder="Enter arbitrary discount" data-bind="enable: enableArbitrary, value: arbitrary, hasFocus: enableArbitrary">
</div>
</div>
<div class="form-group row">
<div class="col-xs-1">
</div>
<div class="col-xs-1">
<input name="discount" type="radio" value="percent" data-bind="checked: discountValue" />
</div>
<div class="col-xs-4">
<label for="percent" data-bind="click: onPercent">Discount percent</label>
</div>
<div class="col-xs-5">
<input type="text" class="form-control" id="percent" placeholder="Enter percent of discount" data-bind="enable: enablePercent, value: percent, hasFocus: enablePercent">
</div>
</div>
<div class="form-group row">
<div class="col-xs-1">
</div>
<div class="col-xs-1">
<input name="discount" type="radio" value="permanent" data-bind="checked: discountValue" />
</div>
<div class="col-xs-4">
<label for="permanent" data-bind="click: onPermanent">Discount permanent</label>
</div>
<div class="col-xs-5">
<input type="text" class="form-control" id="permanent" placeholder="Enter permanent discount" data-bind="enable: enablePermanent, value: permanent, hasFocus: enablePermanent">
</div>
</div>
The problem is that by clicking the radio button, two things happen:
The checked binding does its thing
The event bubbles up to the parent element, and the click binding also does its thing.
You'll have to make sure clicking the input element stops the click binding from firing.
There's a great answer by R.P. Niemeyer here: https://stackoverflow.com/a/14321399/3297291