Make form dynamicly add input with number - forms

can anyone make these functions simple?
i have a ul:
<ul class="phone-type">
<li class="office" id="1"></li>
<li class="mobile" id="2"></li>
<li class="fax" id="3"></li>
</ul>
and the JS :
var o = 0;var m = 0;var f = 0;
$('ul.phone-type li.office').click(function () {
o++;
$('.phones').append('<input class="form-control phone_type" placeholder="'+ $(this).text()+'-'+o+'" name="phone['+$(this).attr('class')+'-'+o+']" type="text" ><br>');
});
$('ul.phone-type li.mobile').click(function () {
m++;
$('.phones').append('<input class="form-control phone_type" placeholder="'+ $(this).text()+'-'+m+'" name="phone['+$(this).attr('class')+'-'+m+']" type="text" ><br>');
});
$('ul.phone-type li.fax').click(function () {
f++;
$('.phones').append('<input class="form-control phone_type" placeholder="'+ $(this).text()+'-'+f+'" name="phone['+$(this).attr('class')+'-'+f+']" type="text" ><br>');
});
i have to reset it for every li..
is there any way that i can make it simple!!!!
tnx

This method will allow for an indefinite number of clickable list elements. Just ensure that you provide the 'data-type' attribute in any elements that are included.
When storing data in an html element, it is usually best to use the 'data' attribute. Using classes only works when there is one class.
HTML
<ul class="phone-type">
<li data-type="office" id="1">office</li>
<li data-type="mobile" id="2">mobile</li>
<li data-type="fax" id="3">fax</li>
</ul>
<div class="phones"></div>
JS
// This object will contain how many clicks each element has
var typeClicks = {};
$('ul.phone-type li').click(function() {
var li = $(this),
type = li.data('type'),
text = li.text(),
clicks;
// check if typeClicks contains any click data for this element
if (typeClicks.hasOwnProperty(type)) {
// if it does, increases tracked clicks by one
typeClicks[type]++;
clicks = typeClicks[type];
} else {
// if not, this will create an entry for this element
clicks = typeClicks[type] = 1;
}
// if not, this will create an entry for this element
$('.phones').append('<input class="form-control phone_type" placeholder="'+text+'-'+clicks+'" name="phone['+type+'-'+clicks+']" type="text" ><br>');
});

Related

How can i dynamically add an Input select element on click of a button in ember

Am creating an ember application where am in need of dynamicaly adding a select element which will have options fetched from a server. so the select elements look like this. And instead of having all dropdown boxes predefined i need to add them dynamicaly like on a click of a button like( + add more). like
and each of those drop down boxes should contain the datas that is fetched from the server. plus i need a way to get the datas from those dynamically created select fields.
my .hbs for the current drop down page is..
map.hbs
<center><h4>Map</h4></center>
<container class = "cond">
{{#each this.model.sf as |row|}}
<select class = "sel">
{{#each this.model.sf as |sf|}}
<option value = {{sf.attrname}}>{{sf.attrname}}</option>
{{/each}}
</select><br>
{{/each}}
I tried ember-dynamic-fields but its depracted and I couldnt able to use it.. and all other solutions on web or for ember way older versions.. nothing works on ember 4.6 so could anyone helpout?
Using The Platform's native FormData functionality, demo'd here.
I think we can generate any number of inputs based on input data in the following way:
Store the form's state in some variable
conditionally show further select / inputs based on the properties in that form state.
Code-wise, that'd look like this:
{{#if (dataHasValueFor "fieldName")}}
Show previously hidden field
{{/if}}
And of course the devil is in the implementation details, so, a full working example (with sample data I made up -- we can iterate on this if you want for your specific data set, just leave a comment on this post/answer).
import Component from '#glimmer/component';
import { tracked } from '#glimmer/tracking';
import { on } from '#ember/modifier';
import { get } from '#ember/helper';
// This could be your model data from your route
const DATA = {
fruits: [
'apple', 'banana', 'orange', 'mango',
'watermellon', 'avacado', 'tomato?'
],
veggies: ['cocumber', 'tomato?', 'green bean', 'kale', 'spinach'],
peppers: ['carolina reaper', 'habanero', 'jalapeƱo']
}
export default class Demo extends Component {
#tracked formData;
get categories() {
return Object.keys(DATA);
}
handleInput = (event) => {
let formData = new FormData(event.currentTarget);
let data = Object.fromEntries(formData.entries());
this.formData = data;
}
handleSubmit = (event) => {
event.preventDefault();
handleInput(event);
}
isSelected = (name, value) => this.formData?.[name] === value;
<template>
<form
{{on 'input' this.handleInput}}
{{on 'submit' this.handleSubmit}}
>
<label>
Food Category<br>
<select name="category" placeholder="Select...">
<option selected disabled>Select a food group</option>
{{#each this.categories as |name|}}
<option
value={{name}}
selected={{this.isSelected "category" name}}
>
{{name}}
</option>
{{/each}}
</select>
</label>
<hr>
{{#let (get this.formData "category") as |selectedCategory|}}
{{#if selectedCategory}}
<label>
{{selectedCategory}}<br>
<select name={{selectedCategory}}>
<option selected disabled>
Select {{selectedCategory}}
</option>
{{#each (get DATA selectedCategory) as |food|}}
<option
value={{food}}
selected={{this.isSelected selectedCategory food}}
>
{{food}}
</option>
{{/each}}
</select>
</label>
{{/if}}
{{/let}}
</form>
<hr>
FormData:
<pre>{{toJson this.formData}}</pre>
</template>
}
const toJson = (input) => JSON.stringify(input, null, 4);
This demo is interactive here, on limber.glimdown.com
Note that the syntax used here is what will be default in the upcoming Polaris Edition of Ember, and is available via ember-template-imports
Update (after comments)
Demo here
I took some liberties with the how the fields are dynamic, because I think this more easily shows the concept asked about in the question: dynamically showing fields in a form.
import Component from '#glimmer/component';
import { tracked } from '#glimmer/tracking';
import { on } from '#ember/modifier';
import { get } from '#ember/helper';
export default class Demo extends Component {
#tracked formData;
handleInput = (event) => {
let formData = new FormData(event.currentTarget);
let data = Object.fromEntries(formData.entries());
this.formData = data;
}
handleSubmit = (event) => {
event.preventDefault();
handleInput(event);
}
<template>
<form
{{on 'input' this.handleInput}}
{{on 'submit' this.handleSubmit}}
>
<div class="grid">
<label>
Name <input type="checkbox" name='hasName'>
</label>
<label>
Email <input type="checkbox" name='hasEmail'>
</label>
<label>
Alias <input type="checkbox" name='hasAlias'>
</label>
<hr>
{{#if (get this.formData 'hasName')}}
<label>
Name
<input type="text" name="name" class="border" />
</label>
{{/if}}
{{#if (get this.formData 'hasEmail')}}
<label>
Email
<input type="email" name="email" class="border" />
</label>
{{/if}}
{{#if (get this.formData 'hasAlias')}}
<label>
Alias
<input type="text" name="alias" class="border" />
</label>
{{/if}}
</div>
</form>
<hr>
FormData:
<pre>{{toJson this.formData}}</pre>
</template>
}
const toJson = (input) => JSON.stringify(input, null, 4);
And... since it seems you have a lot of fields, you may want to go as dynamic as possible:
demo here
which is the following code:
<form
{{on 'input' this.handleInput}}
{{on 'submit' this.handleSubmit}}
>
<div class="grid">
{{#each FIELDS as |field|}}
<label>
{{field}} <input type="checkbox" name='has-{{field}}'>
</label>
{{/each}}
<hr>
{{#each FIELDS as |field|}}
{{#if (get this.formData (concat 'has-' field))}}
<label>
{{field}}
<input type="text" name={{field}} class="border" />
</label>
{{/if}}
{{/each}}
</div>
</form>
I guess Simple js code did the magic of adding and retriving data.. pity of me after finding out.. And for some dynamic ember formdata the previous answer from nullvox helped out.. so here is the code
.hbs
<table class="table">
<th>
<td>Sf</td>
</th>
<th>
<td>Db</td>
</th>
<tbody id = "map">
</tbody>
</table>
<button class = "btn btn-sm btn-primary" type="button" {{action "submit"}}>Submit</button>
<button class = "btn btn-success btn-sm" onclick = {{action "get"}} type="button">Add another</button>
controller code for creating element
#action
get() {
let div = document.getElementById('map');
let tr = document.createElement('tr');
let td = document.createElement('td');
let td2 = document.createElement('td');
var select = document.createElement('select');
select.setAttribute('class', 'sfselect');
div.appendChild(tr);
tr.appendChild(td);
td.appendChild(select);
for (var i = 0; i < sf.length; i++) {
var option = document.createElement('option');
option.value = sf[i];
option.text = sf[i];
select.appendChild(option);
}
var select2 = document.createElement('select');
select2.setAttribute('class', 'dbselect');
tr.appendChild(td2);
td2.appendChild(select2);
for (var i = 0; i < db.length; i++) {
var option = document.createElement('option');
option.value = db[i];
option.text = db[i];
select2.appendChild(option);
}
}
controller code for getting data
#action submit() {
var sfattr = document.querySelectorAll('.sfselect');
var dbattr = document.querySelectorAll('.dbselect');
var sf = [];
var db = [];
console.log(sfattr.length);
let datas;
for (var i = 0; i < sfattr.length; i++) {
sf[i] = sfattr[i].value;
db[i] = dbattr[i].value;
}
let m1 = sf.toString();
let m2 = db.toString();
$.ajax({
url: 'http://localhost:8080/lorduoauth/Map',
method: 'POST',
contentType: 'application/x-www-form-urlencoded',
data: {
m1: m1,
m2: m2,
},
success: function (response) {
console.log(datas);
alert(response);
},
error: function (xhr, status, error) {
var errorMessage = xhr.status + ': ' + xhr.statusText;
alert('error' + errorMessage);
},
});
}
thus the output looks like this

Skip elements within a container when querying DOM

When using querySelectorAll or any DOM query method, I want to skip elements within a given sub-container from querying.
Example:
<div id="container-one">
<div>
<input type="text" name="first">
<input type="text" name="second">
<!-- skip below -->
<div id="container-two">
<input type="text" name="third">
<input type="text" name="fourth">
</div>
<div>
</div>
Suppose in the above case, if you are querying from #container-one element you want to skip elements within #container-two. So the query on #container-one should only return [first, second] elements and skip others (third, fourth).
Appreciate any inputs.
Try this:
document.querySelectorAll('div.container-one')[0].querySelectorAll(':scope > input')
Update(You can't use querySelectorAll for this then):
inputs = document.getElementsByTagName("input");
input_two = document.getElementById('container-two').getElementsByTagName('input');
var input_cont_two_name_array = [];
for(j=0;j<input_two.length;j++){
input_cont_two_name_array.push(input_two[j].name);
}
for(i=0;i<inputs.length;i++){
input_name_id = inputs[i].name;
if(input_cont_two_name_array.indexOf(input_name_id) == -1){
//do your stuff
}
}

angular 2, validate form if at least one input is typed

I'm quite new to Angular, and I've already searched the web, without finding a correct solution for my situation.
I have a dynamic form created by a *ngFor. I need to disabled the submit button if the inputs are all empty and show the alert div; but I need to enable the submit if at least one of those forms contains something different from ''.
Here is my html code
<form class="form-inline" #form="ngForm">
<div class="form-group" *ngFor="let meta of state.metaById; let i = index" style="margin: 5px">
<label>{{meta.nome}}</label>
<input type="text" class="form-control" #nome (blur)="inputInArray(nome.value, i);">
</div>
<button type="button" class="btn btn-primary" (click)="getCustomUnitaDocumentaliRow(this.param)" [disabled]="fieldNotCompiled">invia</button>
</form>
<div class="alert-notification" [hidden]="!fieldNotCompiled">
<div class="alert alert-danger">
<strong>Va compilato almeno un campo.</strong>
</div>
</div>
and here is my Typescript code
inputInArray(nome: string, indice) {
if (this.state.controlloMetaId = true) {
this.state.metadatoForm[indice] = nome;
}
// this.fieldNotCompiled = false;
for (const i in this.state.metaById) {
console.log(this.state.metadatoForm);
if (isUndefined(this.state.metadatoForm[i]) || this.state.metadatoForm[i] === '') {
this.fieldNotCompiled = true && this.fieldNotCompiled;
} else {
this.fieldNotCompiled = false && this.fieldNotCompiled;
}
console.log(this.fieldNotCompiled);
}
With this code I can check the first time a user type something in one input, but it fails if it empty one of them (or all of them)
Thanks for your time
UPDATE
Check if any input got a change that is different from empty or space, just by doing:
<input ... #nome (input)="fieldNotCompiled = !nome.value.trim()" ....>
DEMO
You can set a listener to the form changes:
#ViewChild('form') myForm: NgForm;
....
ngOnInit() {
this.myForm.valueChanges.subscribe((value: any) => {
console.log("One of the inputs has changed");
});
}

jQuery Isotope Filtering Reset

I'm using JQuery Isotope with a combination, three-level filter. In all the examples I've come across, the only way to "reset" the filters is by clicking a "Show All" option.
Is it possible to "un-filter" results by clicking on a selected filter to un-select it?
Here is an example: http://jsfiddle.net/RevConcept/suagb/
Here is my code...
HTML
<div id="options" class="combo-filters">
<div class="option-combo location">
<ul class="filter option-set group level-one" data-filter-group="location">
<li class="hidden">any
<li>exterior
<li>interior
</ul>
</div>
<div class="option-combo illumination">
<ul class="filter option-set group level-two" data-filter-group="illumination">
<li class="hidden">any
<li>illuminated
<li>non-illuminated
</ul>
</div>
<div class="option-combo mount">
<ul class="filter option-set group level-three" data-filter-group="mount">
<li class="hidden">any
<li>wall
<li>ground
</ul>
</div>
</div><!--end options-->
CSS
header nav a {
color:#666666;
}
header nav a.selected {
color:#000000;
}
JAVASCRIPT
$(function(){
var $container = $('#container'),
filters = {};
$container.isotope({
itemSelector : '.project',
masonry: {
columnWidth: 80
}
});
// filter buttons
$('.filter a').click(function(){
var $this = $(this);
// don't proceed if already selected
if ( $this.hasClass('selected') ) {
return;
}
var $optionSet = $this.parents('.option-set');
// change selected class
$optionSet.find('.selected').removeClass('selected');
$this.addClass('selected');
// store filter value in object
// i.e. filters.location = 'exterior'
var group = $optionSet.attr('data-filter-group');
filters[ group ] = $this.attr('data-filter-value');
// convert object into array
var isoFilters = [];
for ( var prop in filters ) {
isoFilters.push( filters[ prop ] )
}
var selector = isoFilters.join('');
$container.isotope({ filter: selector });
return false;
});
});
You could add a "Reload Page" button...
Here are 3 examples for you...
<input type="button" value="Reload Page" onClick="window.location.href=window.location.href">
<input type="button" value="Reload Page" onClick="window.location.reload()">
<input type="button" value="Reload Page" onClick="history.go(0)">
isoSelective provides combining and toggling filters. Try using my updated version: https://github.com/simmerdesign/jquery-isoselective

dynamic creation of textbox

while i create textbox dynamically i can able to add any no
of textbox while i delete only last textbox got deleted after it
an throws exception.
<html>
<head>My page </html>
<body>
<div id="firstdiv">
<input type="text" id="text" id="text1" value=""/>
<input type="button" id="butt" name="it's okay" value="+" onclick="text_add()"/>
<input type="button" id="butt1" name="it's okay" value="-" nclick="text_remove()"/>
</div>
</body>
<script type="text/javascript">
var i=0;
function text_add()
{
++i;
var bal=document.createElement("input")
bal.setAttribute("type","text");
bal.setAttribute("id","text"+i);
bal.setAttribute("name","bala");
firstdiv.appendChild(bal);
}
function text_remove()
{
try{
var a="\"";
a+="text"+(i);
a+="\"";
alert(a);
var bal=document.getElementById(a);
firstdiv.removeChild(bal);
--i;
}catch(e)
{
alert("Echo"+e);
}
}
</script>
</html>
chorme throws error: after deleting one text box like
EchoError: NOT_FOUND_ERR: DOM Exception 8
so you whant to add and remove textboxes.
and the latest textbox added shuld be removed?
so first you alreddy have a textbox in the dom witch will colide with your
naming
<input type="text" id="text" id="text1" value=""/>
is this an atemt to manualy add qoutes ? becus thats not part of the id
of the element
var a="\"";
a+="text"+(i);
a+="\"";
just give it the name normaly
var bal = document.getElementById("text" + i);
and you dont have to mess around with dom ids you can store
dom elements as normal objects so
something like this works fine
var textElements = [];
var firstdiv = document.getElementById("firstdiv");
function text_add() {
var bal = document.createElement("input");
bal.setAttribute("type","text");
bal.setAttribute("name","bala");
firstdiv.appendChild(bal);
textElements.push(bal);
}
function text_remove() {
firstdiv.removeChild(textElements.pop());
}
the pop method removes the last added item in the array