Adding of users to dropdown list doesn't work - javascript

Good evening!
There's a problem with adding a user to dropdown list (ui-grid is used).
I need to push input name by id into dd list after the "addNewPerson" button is clicked, if there's no such name in the list, or to call "alert", if there is.
Here's a code, responsible for the dd list creation in html:
<ui-select ng-model="person.selected" theme="select2" style="min-width:300px;">
<ui-select-match placeholder="Select a person in the list or search by name">{{$select.selected.name}}
</ui-select-match>
<ui-select-choices repeat="person in contacts | filter: {name: $select.search} track by $index">
<div ng-bind-html="person.name | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
Button and input field:
<button type="button" id="addPerson" class="button" ng- click="addNewPerson()">Add New Person</button>
<input id="name" class="form-control" placeholder="Enter your Name">
Array of objects with the "name" field, which needs to be passed into the dd list:
$scope.contacts = [
{name: "Han Solo"},
{name: "ThetaSigma"},
{name: "Ollie Reeder"},
{name: "Amy McDonald"},
{name: "PJ Harvey"},
{name: "Sofie Marceau"},
{name: "Arthur Zimmermann"},
{name: "Michelle Dockery"},
{name: "Xavier Dolan"}
];
And, at last, the notorious function:
$scope.person = {};
$scope.addNewPerson = function () {
var nameInput = document.getElementById("name");
for (var i=0; i <= $scope.contacts.length; i++) {
if ($scope.contacts[i].name == nameInput.value.toLowerCase()) {
alert("Error, the name entered already exists");
}else{
var obj1 = {name: nameInput.value};
$scope.contacts.push(obj1);
}
}
};
I've tried various formations of the function, it either pushes nothing and alerts 10 times, or pushes names correctly, but even already existing ones, or pushes 10 times and alerts 10 times after a single adding.
I'm handicapped. Tried to find similar q/a here, but to no avail.
And sorry for my english, it'snot my native language.

Here's working codepen example.
First Change the html for the input to use scope variable:
<input ng-model="name" class="form-control" placeholder="Enter your Name">
and in the controller:
$scope.name = "";
$scope.addNewPerson = function () {
for (var i=0; i < $scope.contacts.length; i++) {
if ($scope.contacts[i].name.toLowerCase() === $scope.name.toLowerCase()) {
alert("Error, the name entered already exists");
return;
}
}
$scope.contacts.push({name: $scope.name});
};

You ng-model to bind the new user name:
<input id="name" class="form-control" placeholder="Enter your Name" ng-model="new_user_name">
Then in your js, you have to break out of your forloop :
$scope.person = {};
$scope.addNewPerson = function () {
var name = $scope.new_user_name || "";
var match_found = false;
for (var i=0; i <= $scope.contacts.length; i++) {
if ($scope.contacts[i].name == name.toLowerCase()) {
alert("Error, the name entered already exists");
match_found = true;
break;
}
}
if (!match_found) {
var obj1 = {name: name};
$scope.contacts.push(obj1);
}
};

The above answers are fine, I would just like to add the option to use functional programming style as I love to do it and for me it looks cleaner.
View
<input ng-model="name" class="form-control" placeholder="Enter your Name">
Controller
$scope.name = "";
$scope.addNewPerson = function () {
var contactIndex = $scope.contacts.map(function (contact) {
return contact.name.toLowerCase();
}).indexOf($scope.name.toLowerCase());
if (contactIndex === -1)
$scope.contacts.push({name: $scope.name});
else
console.log("Error, the name entered already exists");
}
A few notes:
When working with angular, never access DOM in view controllers, use directives instead
Functional programming style will save you a lot of typing
Using console.log instead of alerting boosts your productivity by approx. 9000%

Related

Auto write input fields value to textarea with separator jquery

I have a few input fields
<input type="text" placeholder="name">
<input type="text" placeholder="age">
<input type="text" placeholder="gender">
<input type="text" placeholder="interest">
and every time I write on those input fields it should reflect to the textarea and output a format with | or pipe symbol
Example:
<textarea>
name|age|gender|interest
</textarea>
and when I add another set of fields it writes it on the second line
<textarea>
name|age|gender|interest
name|age|gender|interest
name|age|gender|interest
</textarea>
Also "Number of Children" quantity needs to adjust automatically based on per line in the text area or how many children.
Here is My fiddle to make it more clearer https://jsfiddle.net/sjgrLcqx/4/
I did a few things here.
I made your HTML string a single variable so that when I changed it I didn't have to do so twice.
I added classes to your inputs so that I could figure out which one the user is typing into.
I used a few jQuery methods you might not be aware of, like index() and parent().
I used a few JavaScript functions to iterate through the properties on the child object I created to make creating a string from its attributes easier.
Look over the code and let me know if you have any questions. Also, next time, maybe try this yourself, even if you have no idea where to start. Just keep trying stuff until something starts to work. Coding is challenging but that's what's fun about it.
jQuery(document).ready(function () {
var childInfoArray = [];
var formHtml = '<div class="optionBox"><div class="block" style=""><input class="crow fullName" type="text" placeholder="Full name"><input class="crow width50 marginsmall age" type="text" placeholder="Age"><input class="crow width50 nomargin gender" type="text" placeholder="gender"><input class="crow interest" type="text" placeholder="Interest"><span class="remove">Remove this section</span></div><div class="block"><span class="add">Add another child\'s info</span></div></div>';
jQuery('#frmPaymentSantasgrotto').append(formHtml);
jQuery('.add').click(function () {
jQuery('.block:last').before(formHtml);
});
jQuery('.optionBox').on('click', '.remove', function () {
jQuery(this).parent().remove();
});
jQuery('.optionBox').on('keyup', 'input', function () {
var index = $(this).parent().index('div.block');
var child = {};
if (childInfoArray[index] != null) {
child = childInfoArray[index];
}
else {
child = {
fullName: '',
age: '',
gender: '',
interest: ''
}
}
if ($(this).hasClass('fullName')) {
child.fullName = jQuery(this).val();
}
else if ($(this).hasClass('age')) {
child.age = jQuery(this).val();
}
else if ($(this).hasClass('gender')) {
child.gender = jQuery(this).val();
}
else if ($(this).hasClass('interest')) {
child.interest = jQuery(this).val();
}
childInfoArray[index] = child;
printChildArray();
});
function printChildArray() {
var childInfoString = "";
childInfoArray.forEach(child => {
Object.values(child).forEach((attribute, index) => {
childInfoString += attribute;
if (index !== Object.keys(child).length - 1) {
childInfoString += ' | ';
}
else {
childInfoString += ' \n';
}
});
});
$('textarea').html(childInfoString);
}
});

Take an input value and see if it equals the defined object

HTML:
<html>
<body>
<input type = "text" name = "name" id = "name"> </input>
<button type = "submit" id = "submit">Find Student </button>
<script type = "text/javascript" src="ObjectTest.js"></script>
</body>
</html>
Javascript:
var Matt = {
GPA: 4.0,
Faculty: "Science",
Year: 1
};
I have an object that I've defined with some values.
What I am trying to do is to allow text to be entered into the textbox.
When the submit button is hit, a javascript function will be run that grabs the value in the textbox and if it equals the object value, then it will console.log the properties.
Here is my better attempt:
function findStudent(){
var student = document.getElementById('name').value;
return student;
}
console.log(student);
Hard to know exactly what you're trying to achieve or where your object is coming from but your object probably needs to look something like:
var student = {
name:'Matt',
gpa:4.0,
faculty:'Science',
year: 1
}
Try something like:
function checkName(){
var name = document.getElementById('name').val();
if(name === student.name){
console.log('same');
}
else{
console.log('different');
}
}
Called in your button, with something like:
<button onclick="checkName()">Check Student</button>
You have to think about the structure. There should be a lot of students. It's not practical to set multiple objects for each student:
var st1 = { ... }
var st2 = { ... }
Instead it's more practical to declare one object with all students. And put the values in an array:
var students = {
"Matt": ["4.0", "science", "1.0"],
"Laura": ["3.0", "comedy", "2.2"],
...
}
You can output the array as an info to the corresponding student:
function findStudent() {
var info = [];
var student = document.getElementById("name").value;
for (name in students) {
if (name === student) {
info = students[name];
}
}
alert(info);
}
JSFiddle
If you want to use a submit button, it should be in a form. This also makes dealing with inputs easier, even if you don't want to submit the form. I've modified the object so that it has a name property.
var Matt = {
name: 'Matt',
GPA: 4.0,
Faculty: "Science",
Year: 1
};
function checkValue(form) {
if (form.studentName.value == Matt.name) {
form.output.value = ('Match');
} else {
form.output.value = ('Not a match');
}
return false;
}
<form onsubmit="return checkValue(this);">
<label for="studentName">Name: <input name="studentName" id="studentName"></label>
<button>Check the name</button>
<br>
<label for="output">Output: <input name="output" id="output"></label>
</form>
The body of the checkValue function could be:
form.output.value = form.studentName.value == Matt.name? 'Match' : 'Not a match';
However the longer version is simpler to understand.

How to reflect the current value in a drop-down field after populating options in a select control(ng-options) in AngularJS?

The discussion revolves around an application which can be visualized as,
As seen clearly, as the user clicks on one of the stories on the left hand side, the right-hand side fields are populated with the content corresponding to that story.
Every story has a title and a status,
service:
myModule.service('AngelloModel', function(){
var service = this;
var stories = [
{
title: 'First story',
status: 'To Do',
},
{
title: 'Second story',
status: 'Back Log',
},
{
title: 'Another story',
status: 'Code Review',
}
];
var statuses = [
{name: 'Back Log'},
{name: 'To Do'},
{name: 'In Progress'},
{name: 'Code Review'},
{name: 'QA Review'},
{name: 'Verified'},
{name: 'Done'}
];
service.getStories = function(){
return stories;
}
service.getStatuses = function(){
return statuses;
}
})
factory( a helper/utility function):
myModule.factory('AngelloHelper', function() {
var buildIndex = function(array, property) {
var tempArray = [];
for (var i = 0; i < array.length; i++) {
tempArray[array[i][property]] = array[i];
}
return tempArray;
}
return {
buildIndex : buildIndex
}
})
controller and module:
var myModule = angular.module('Angello',[]);
myModule.controller('MainCtrl',function(AngelloModel, AngelloHelper){
var main = this;
main.stories = AngelloModel.getStories();
main.statuses = AngelloModel.getStatuses();
main.statusesIndex = AngelloHelper.buildIndex(main.statuses, 'name');
main.setCurrentStory = function(story){
main.currentStory = story;
//alert(story.status); // (To Do) if I click on first story
main.currentStatus = main.statusesIndex[story.status];
//alert(main.currentStatus); // {name: 'To Do'} if I click on first story
//alert(main.currentStatus.name); // hence it will be (To Do)
}
})
html:
<body>
<div ng-controller="MainCtrl as main">
<div class="col-md-4">
<h2>Stories</h2>
<div class="callout" ng-repeat="story in main.stories"
ng-click="main.setCurrentStory(story)">
<h4>{{story.title}}</h4>
<p>{{story.description}}</p>
</div>
</div>
<div class="col-md-6 content">
<h2>Story</h2>
<form class="form-horizontal">
<div class="form-group">
<label class="control-label" for="inputTitle">Title</label>
<div class="controls">
<input type="text" class="form-control"
id="inputTitle" placeholder="Title" ng-model="main.currentStory.title" />
</div>
</div>
<div class="form-group">
<div class="controls">
<select id="inputStatus" class="form-control"
ng-model="main.currentStatus.name"
ng-options="l.name for l in main.statuses"></select>
</div>
</div>
</form>
</div>
</div>
</div>
</body>
Consider this one which is the whole point of discussion :
<select id="inputStatus" class="form-control"
ng-model="main.currentStatus.name"
ng-options="l.name for l in main.statuses"></select>
In the figure at the top, you can see the values in the drop-down field, which is done by
ng-options="l.name for l in main.statuses"
However, the current value is not reflected on selecting a story, even though I have done,
ng-model="main.currentStatus.name"
Any suggestions?
Looking at the ng-model you are trying to assign name as the unique identifier for options, so you may want to use select as i.e
ng-options="l.name as l.name for l in main.statuses"
This will make sure the ng-model (ng-model="main.currentStatus.name") is populated with the right name and your dropdown will be preselected with the value set in the ng-model property.
However if you are setting an object with array of objects as this with just one property you might as well set a unique identifier (if name is not one) or just use array of names.
Also with this you can removing the mapping logic (main.statusesIndex = AngelloHelper.buildIndex(main.statuses, 'name');) and just do:
main.currentStatus = {name: story.status};
or even set your ng-model as
<select id="inputStatus" class="form-control"
ng-model="main.currentStatus"
ng-options="l.name as l.name for l in main.statuses">
</select>
and
main.currentStatus = story.status;

AngularJS Add More Option For Input Type File

Suppose I want to add 'Add More' button next to input type file field.
So that on click of 'Add More' button one more file field will be created.
I could use '.clone()' for this in JQuery.
But how will I do this in AngularJS?
Thanks!!
In controller:
$scope.addMore = function() {
$scope.inputs += 1;
};
$scope.range = function(count) {
var inputs = [];
for (var i = 0; i < count; i++) {
inputs.push(i)
}
return inputs;
}
$scope.inputs = 0;
In HTML:
<input ng-repeat="n in range(inputs)">
<button ng-click="addMore()">Add more!</button>
MORE USEFUL VERSION:
Typically you want to have other information related to the input field though, so depending on your use case, you might just want to have an array of input objects with some properties, and then ng-repeat over that array like following:
Controller:
$scope.inputs = [];
$scope.addMore = function() {
$scope.inputs.push({
id: $scope.inputs.length,
text: "Initial text here"
})
};
HTML:
<input ng-repeat="input in inputs" ng-model="inputs[$index].text">
<button ng-click="addMore()">Add more!</button>
What you want to do is to create an array of input button.
display your input array :
<div ng-repeat="item in items"><input type="text" ng-model="item.value"><div>
attach a function to the ng-click of your button :
<button ng-click="addMore()">Add More</button>
and then define your array in controller :
$scope.items = [];
$scope.addMore = function () {
$scope.items.push({
value:'default'
});

Looping through a form and populating from an object

I have a form and a javascript object.
<form id="myForm">
<input type="text" name="title">
<input type="text" name="image">
</form>
var myObject = {title: 'this is the title', image: 'image.jpg'}
Is there a way to run through the form inputs, and it any of the input names match the keys in the object, set the value?
Please note, I wish to run through the form and not the object, as the object has lots of other data in it which is not relevant to the form (not shown in example).
You can do:
$("#myForm input:text[name]").each(function() {
var name = $(this).attr("name");
for (var key in myObject) {
if (key == name) {
$(this).val(myObject[key])
break;
}
}
});
With this you don't ever loop the object, but you'll have to write an if-clause for every attribute:
var myObject = {title: 'this is the title', image: 'image.jpg'}
$('#myForm input').each(function()
{
if($(this).attr('name') === 'title')
{
$(this).val(myObject.title);
}
});

Categories