Javascript prevent "undefined" value with dynamic array - javascript

I have dynamic form elements and trying to add values to input's value attribute which is coming from as a array. However sometimes there are no any data ,then javascript prints undefined to value area of the input element.
How can i check it and dont print undefined in dynamic element?
$("#test").append("<input type='text' name='first-test' class='form-control' value='"+testarray['first-test']+"' >
When we check the textbox , it shows "undefined" as a value.

I think this will work
$("#test").append("<input type='text' name='first-test' class='form-control' value='"+(testarray['first-test']===undefined ? "Insert here what ever you want when it is empty.":testarray['first-test'])+"'>");
https://jsfiddle.net/b51gq0mq/2/

Here is working example, we pass an array with objects into our function. For loop simply skips if value is not found.
var yourArray = [
{ name: 'Janet' },
{ name: 'Jane', value: 1 },
{ name: 'Tom', value: 2 },
{ name: 'Kate', value: 3},
{ name: 'Mark' },
{ name: 'Tom' }
];
function addInputs(array) {
for (i = 0; i < array.length; i++) {
var element = array[i];
// Skips if no value found
if (element.value === undefined) {
continue;
}
var html = '<input type="text" name="' + element.name + '" class="form-control" value="' + element.value + '" />';
$('#test').append(html);
}
};
addInputs(yourArray);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="test"></div>

Related

Angular: Eventhandling Problems with JS generated Code OR not being able to add classes to HTML generated Code with *ngfor

My problem is the following:
I have stations I want to display inside a modal window, whereas the already selected Stations should be coloured blue and the not selected ones should be gray.
All stations are in an array called "allStations" and the already selected stations are in "currentStations".
However, I have multiple problems with this:
First off:
I either generate this in HTML with a *for loop, then I have the problem, that I am not able to assign the classes that should colour each one.
<jw-modal id="ov_stations">
<div id="allstationsdiv">
<p *ngFor="let st of allStations" id="{{ st.id }}" class="notselected"(click)="onstationclick({{st.id}})">
{{ st.name }}
</p>
</div>
<span (click)="closemodal()"><img src="../../../../assets/icons/x.png" alt=""></span>
</jw-modal>
I tried to solve this by generating the HTML inside the openmodal() function, which opens the modal in the first place instead of directly in the HTML:
openmodal(){
this.modalService.open("ov_stations");
let output = document.getElementById("allstationsdiv");
let dealtwith = [];
if (output.childElementCount == 0){
for (var i = 0; i < this.allStations.length; i++){
if (this.currentStations.length == 0)
output.innerHTML += "<p id='" + this.allStations[i].id + "' class='notselected' (click)='onstationclick(" + this.allStations[i].id + ")'>" + this.allStations[i].name + "</p>";
else {
// noch weiter testen
for (var j = 0; j < this.currentStations.length; j++){
if (this.currentStations[j].id == this.allStations[i].id){
output.innerHTML += "<p id='" + this.allStations[i].id + "' class='selected' (click)='onstationclick(" + this.allStations[i].id + ")'>" + this.allStations[i].name + "</p>";
dealtwith.push(this.allStations[i].id);
// console.log("selected: " + this.allStations[i].id + " and dealt with: " + dealtwith[i]);
} // && this.allStations[i].id != dealtwith[i]
else if (this.currentStations[j].id != this.allStations[i].id){
output.innerHTML += "<p id='" + this.allStations[i].id + "' class='notselected' (click)='onstationclick(" + this.allStations[i].id + ")'>" + this.allStations[i].name + "</p>";
dealtwith.push(this.allStations[i].id);
// console.log("notselected: " + this.allStations[i].id + " and dealt with: " + dealtwith[i]);
}
console.log(dealtwith);
console.log(this.allStations[i].id);
}
}
}
}
}
(I am aware that the loop doesn't work yet, but that is not my immediate concern)
However, now, when I try to click on a Station to access the function which would change it's class, it does not work anymore, the function is not called upon. I am guessing that this is because I now generate the code inside JS instead of from HTML.
How can I solve this problem?
Is there a way to give the p's the correct class with the conditions above?
Or is there a way to solve the problem of not being able to get a click function to work from JS?
I would prefer the latter, but if the first one is easier I am willing to try that too.
Thank you very much for your time.
Using the ngClass directive (https://angular.io/api/common/NgClass) will get you the outcome you are looking for. For example:
in your component.html
<div id="allstationsdiv">
<p *ngFor="let st of allStations"
[ngClass]="{
'selected':isStationSelected(st),
'notselected':!isStationSelected(st)
}"
(click)="onstationclick(st.id)">
{{ st.name }}
</p>
</div>
in your component.ts file
export class MyComponent {
allStations = [
{ id: 1, name: "station 1" },
{ id: 2, name: "station 2" },
{ id: 3, name: "station 3" },
{ id: 4, name: "station 4" },
{ id: 5, name: "station 5" }
];
selStations = [{ id: 3, name: "station 3" }, { id: 4, name: "station 4" }];
onstationclick(station): void {
//do something here
}
// will check to see if the currentStations array contains the station id you
// are passing from the all stations array
isStationSelected(station): boolean {
return this.currentStations.some(st=> st.id === station.id);
}
}
in your component.css
.selected {
color: blue
}
.notselected {
color: grey
}
Generally you should avoid generating html code via js in angular, since you have angular itself to do that.

Remove duplicate json when creating hmtl from JSON

I'm trying to populate a div dynamically with data from JSON but want to avoid duplicates. The script below will give me 3 divs, 2 "standard" and one "special".
How can I achieve without creating duplicate div?
var productList = [
{
model:"helskap",
type:"special",
family:"Bravo"
},
{
model:"Z-skap",
type:"standard",
family:"Valhalla"
},
{
model:"smafacksskap",
type:"standard",
family:"Jona"
}
];
$.each(productList, function(i, item) {
$('.filter').append('<div class="' + productList[i].type+ '"><input type="radio" name="type" value="' + productList[i].type+ '" /><label>' + productList[i].type+ '</label></div>')
});
<div class"filter"></div>
The better way is to first get the array with unique objects on property type then you can use that new filtered array for rendering like in filterProductList:
var productList = [{
model: "helskap",
type: "special",
family: "Bravo"
},
{
model: "Z-skap",
type: "standard",
family: "Valhalla"
},
{
model: "smafacksskap",
type: "standard",
family: "Jona"
}
];
var filterProductList = productList.reduce((acc, item) => {
var existItem = acc.find(({type}) => type === item.type);
if (!existItem) {
acc.push(item);
}
return acc;
}, []);
console.log(filterProductList);
Then use filterProductList to render the HTML in your page. Your code will look:
$.each(filterProductList, function(i, item) {
var type = filterProductList[i].type;
$('.filter').append('<div class="' + type + '"><input type="radio" name="type" value="' + type + '" /><label>' + type + '</label></div>')
});
I think the easy way is to create each div with id="type", then append contents to div id="type".

Get last tag data on change

I have this code:
var i = 0;
$('#jobs').change(function() {
var id = $(this).select2('data')[i].id;
var txt = $(this).select2('data')[i].text;
$('#jobSection').append('<fieldset><legend>' + txt + '</legend><input type="text" class="form-control" name="size_' + id + '" placeholder="Size"><br/><select class="form-control" name="type_' + id + '"><option>Type</option><option value="1">Type 1</option><option value="2">Type 2</option></select></fieldset>');
i++
});
With that I am appending extra input fields for each tag.
But it works only if I select tags by order otherwise it takes previous tag data.
I understand that problem is in i because this is not actual loop but change event.
So I want to know how to get just last tag data on change?
Full example is here
var selectOption = [{
"id": 1,
"text": "one"
}, {
"id": 2,
"text": "two"
}, {
"id": 3,
"text": "three"
}, {
"id": 4,
"text": "four"
}, {
"id": 5,
"text": "five"
}];
$('#jobs').select2({
tags: true,
multiple: true,
placeholder: 'Choose job...',
data: selectOption
});
var selectOptionObj = {};
$.each(selectOption, function(i, v) {
selectOptionObj[v.id] = v;
});
$('#jobs').change(function() {
var thisVal = $(this)[0].value.split(',');
var i = thisVal[thisVal.length - 1];
var id = selectOptionObj[i].id;
var txt = selectOptionObj[i].text;
$('#jobSection').append('<fieldset><legend>' + txt + '</legend><input type="text" class="form-control" name="size_' + id + '" placeholder="Size"><br/><select class="form-control" name="type_' + id + '"><option>Type</option><option value="1">Type 1</option><option value="2">Type 2</option></select></fieldset>');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.full.min.js"></script>
<div id="jobSection">
<input type="text" id="jobs">
</div>
Refer : JSFiddle
I think you should redesign your application to rebuild whole #jobSelection node every time selection changed according to current selected elements. This way your #jobSelection structure always be actualized.
I looked through event object and didn't find info about last selected option. So you need to work with current state and not with changes.
If this is not the option, you can always keep previous selection state in some variable and diff it with current state on every onChange event. But I think it is not the best solution for your problem.

How to create radio buttons dynamically with array elements as label for buttons

I want to create radio buttons according to the elements of array that i am calling from database. and this elements should be use as label for each radio button. How i can code for it. I am calling 6 element as username suggestion. and when a guest select any of button then that label for particular button will replace the input name type by guest. Thank You
function showSuggestions() {
var usernames = [
'test1', 'test2', 'test3', 'test4'
];
var result = $('#result');
result.html('');
for (var i = 0; i < usernames.length; i++) {
result.append('<label><input type="radio" name="usernames" value="' + usernames[i] + '" /> ' + usernames[i] + '</label>');
}
}
$('button').click(showSuggestions);
$('#result').on('change', 'input', function() {
var elem = $(this);
if (elem.is(':checked')) {
$('#search').val(elem.val());
}
});
label {
display:block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="search" type="search" /><button>Search</button>
<div id="result"></div>

Javascript - Populating a form dynamically based on one object and filling in the values from another object

I have a JSON object that I use as a Template for all available Fields that can be added to an element in my Object that is used to Store the values.
I have another Object that holds values. The k,v of this Object storing all the values was not generated in my application. It is handed to me and I need to populate that value in a form that is created dynamically based on my JSON which defines all availabl keys for a given element. Its best I show you my demo app.
Demo: http://jsfiddle.net/bGxFC/15/
1. Click "Button_2" label - Notice how it populates a form with 5 k,v inputs
2.Now click "Button_1" label - Notice how this has 6 k,v inputs
3. Both of these are "Type": "Button" but "Button_2" is missing 'Transition' from its inputs
4This is where my 'var controls' object comes in. It defines all the available option that each type can have.
The Problem
I need to alter my code to use the values from 'objStr' and place them into a form that was created by 'controls'. And once I add a value to an empty input(i.e.The 'Transition' input in "Button_2") it will be saved back to 'objStr'.
Here is my code:
var controls = {
"Button":{"Type": "", "Transition": "","BackgroundImage": "","Position": "","Width": "","Height": ""},
"Image":{"Type": "","BackgroundImage": "","Position": "","Width": "","Height": ""},
"Label":{"Type": "","Position": "","Width": "","Height": "","Text": "","FontSize":"","Color": "", "FontType": ""}
};
objStr = {
"View_1":
{
"Image_1":{
"Type":"Image",
"BackgroundImage":"Image.gif",
"Position":[0,0],
"Width":320,
"Height":480
},
"Button_1":{
"Type":"Button",
"BackgroundImage":"Button.gif",
"Transition":"View2",
"Position":[49,80],
"Width":216,
"Height":71
},
"Button_2":{
"Type":"Button",
"BackgroundImage":"Button2.gif",
"Position":[65,217],
"Width":188,
"Height":134},
"Label_1":{
"Type":"Label",
"Position":[106,91],
"Width":96,
"Height":34,
"Text":"Button",
"FontSize":32,
"Color":[0.12549,0.298039,0.364706,1]
}
}
};
$(document).ready(function () {
var $objectList = $('<div id="main" />').appendTo($('#main'));
$.each(objStr.View_1, function(k, v) {
$('<div/>').append(k).appendTo($objectList).on('click', function(){
var $wrapper = $('#form .wrapper').empty();
if(typeof v === 'string') {
$('<div class="item" />').append('<span class="key">' + k + '</span>' + '<input value="' + v + '"/>').appendTo($wrapper);
}
else {//object
$('<h3 class="formHeading" />').append(k).appendTo($wrapper);
$.each(v, function(key, val) {
$('<div class="item" />').append('<span class="key">' + key + '</span>' + '<input value="' + val + '"/>').appendTo($wrapper);
});
}
$("<button>Save</button>").appendTo($wrapper).on('click', function() {
if(typeof v === 'string') {
v = $(this).closest(".wrapper").find("input").val();
}
else {//object
$(this).closest(".wrapper").find(".item").each(function(i, div) {
var $div = $(div),
key = $div.find(".key").text(),
val = $div.find("input").val();
v[key] = val;
});
}
});
});
});
});

Categories

Resources