How to take object input in angularjs - javascript

I have a part of form like this
<input type="text" ng-model="gen.name" ng-repeat="gen in movie.genres">
gen in movie.genre is an object with 2 key value pairs
Object{
id: 24,
name : insidious
}
If I take the values on form submit I only get gen.name as value
but I need the id of gen object as well.
So what can I do to get its id as well?
Please note there are multiple input values as they are inside ng-repeat

You can use Array.findIndex() to find the id of the object which has the name of the selected genre.
Something like this should work (as long movie.genres is an array and valueFromForm is the value you get from your ng-model):
let index = movie.genres.findIndex(gen => gen.name === valueFromForm);
id = movie.genres[index].id;
This code uses ES6 so it needs recent browsers if you do not transcompile.
You can use this other version for older browsers:
var id = -1;
for (var i=0; i < movie.genres.length; i++) {
if (movie.genres[i].name === valueFromForm) {
id = movie.genres[i].id;
break;
}
}

Here is a working example of exactly what you want. I hope this will help you fix your problem:
angular.module('submitExample', [])
.controller('ExampleController', ['$scope', '$log', function($scope, $log) {
$scope.movie = {
title: 'Movie Title',
genres: [{
name: 'Action'
}, {
name: 'Drama'
}, {
name: 'Comedy'
}]
};
$scope.submit = function() {
$log.info($scope.movie);
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.1/angular.min.js"></script>
<div ng-app="submitExample">
<form ng-submit="submit()" ng-controller="ExampleController">
<input ng-model="gen.name" ng-repeat="gen in movie.genres"><br>
<input type="submit" value="Submit">
</form>
</div>

Related

How to checked check box values with existing comma separated values stored in DB using Angular Js

I shows amenities checkbox options as ng-repeat of a json array and i stored into database as comma separated ids like "1,3,7" as a single string but when i need to edit amenities checkbox i am unable to show existing options as checked because i get existing value from db as 1,3,7 as single string how i will check this string with options in the ng-repeat ?
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.amenities=[{id:1,value:"Wifi"},
{id:2,value:"AC"},
{id:3,value:"Creditcard"},
{id:4,value:"24x7"},
{id:5,value:"Parking"},
{id:6,value:"Free delivery"},
{id:7,value:"No Smoking"}
];
//For example assume that this is existing amenities from database
$scope.existamenities="1,3,7";
});
</script>
<htmL>
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-repeat="amn in amenities">
<label>{{amn.value}}
<input type="checkbox" name="amenities" ng-value="amn.id">
</label>
</div>
</div>
</htmL>
I believe for them to be checked you need to set the ng-model to true or false. Simply create another array and populate it accordingly.
You have an option to append the existing array with new properties that will hold true/false values, or create a new array that was mapped from the original one. Then simply switch default false values to true if their ID is listed, which you can get by splitting the string.
Here is a small demo:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.amenities = [
{id:1,value:"Wifi"},
{id:2,value:"AC"},
{id:3,value:"Creditcard"},
{id:4,value:"24x7"},
{id:5,value:"Parking"},
{id:6,value:"Free delivery"},
{id:7,value:"No Smoking"}
];
//For example assume that this is existing amenities from database
$scope.existamenities = "1,3,7";
var a = $scope.existamenities.split(",").map(x => Number(x))
var b = $scope.amenities.map((x) => {
return {
"id": x.id,
"val": false
}
})
for (var i = 0; i < b.length; i++) {
for (var j = 0; j < a.length; j++) {
if (b[i].id == a[j]) {
b[i].val = true
}
}
}
$scope.model = b;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-repeat="amn in amenities">
<label>{{amn.value}}
<input type="checkbox" name="amenities" ng-model="model[$index].val" ng-value="amn.id">
</label>
</div>
You need to use ng-model on each checkbox in order to be able to control if they're checked or not ... and be able to tell which ones are checked at a later point, e.g. form submission.
In order to do that:
Amenities objects should have a checked property
The checkboxes in the ng-repeat should bind ng-model to the checked property
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.amenities=[{id:1,value:"Wifi", checked: false},
{id:2,value:"AC", checked: false},
{id:3,value:"Creditcard", checked: false},
{id:4,value:"24x7", checked: false},
{id:5,value:"Parking", checked: false},
{id:6,value:"Free delivery", checked: false},
{id:7,value:"No Smoking", checked: false}
];
//For example assume that this is existing amenities from database
$scope.existamenities="1,3,7";
var arrayOfExistingAmenities = $scope.existamenities.split(",");
arrayOfExistingAmenities.forEach(function(existingAmenity) {
$scope.amenities.forEach(function(amenity) {
if (amenity.id == parseInt(existingAmenity)) {
amenity.checked = true;
}
});
});
});
</script>
<htmL>
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-repeat="amn in amenities">
<label>{{amn.value}}
<input type="checkbox" name="amenities" ng-model="amn.checked" ng-value="amn.id">
</label>
</div>
</div>
</htmL>

ng repeat on a array to filter a key on another object to get the associated value and use watch on that value

Let say i have a object called,
scope.rec = {a: 2, b: 3, name: a,b};
And i split the "name" key like scope.x = scope.rec.name.split(","); then scope.x will become an array.
Now i need to iterate over "scope.x" in the view and get the value associated with the matching property name on scope.rec. I only want to iterate over the valid property names, so I will need to use a filter on scope.x, but it is not working as I would expect.
Once I get the first part working, I will also need to add functionality to multiply the values of the scope.rec properties together - in the example above, it is only 2 numbers (a,b), but it could be more than 2.
Below is the code that I tried.
scope.x =
scope.rec.name.split(",");
scope.myFilter = function(y) {
if(!scope.rec.hasOwnProperty(y)) return false;
scope.ys = Number(scope.rec[y]);
return scope.ys;
};
html:
<div ng-repeat="y in x | filter:myFilter">
<label for="{{y}}">{{y}}</label>
<input type="number" id="{{y}}" value={{ys}}>
</div>
<div><input id="calc" type="number" ng-model="calc()" disabled></div>
Now the ys in the input is same for both inputs, and the calc() function does not calculate the values correctly.
Appreciate your help in advance.
your filter (at least how you use it in your view) will receive an array with all elements, not just one. So you need to return a complete array
angular.module('myApp').filter('myFilter', function() {
return function(arrayOfYs, recFromScope) {
var filtered = [];
arrayOfYs.forEach(function(y){
if(!recFromScope.hasOwnProperty(y)) return;
// if the value in the object is already a number, it is not necessary to use Number. If it is not the case, add it
filtered.push(scope.rec[y]);
});
return filtered;
}
});
and return the filtered data.
According to your view, you need to use angular filters.
for you input you should use this
<input type="number" id="{{y}}" value={{y}}>
although I would remove that id - ids needs to be unique and probably there are values repeated.
for your calc() function you can use reduce to multiply them
$scope.calc = function(){
return $scope.filteredItems.reduce(function(prev, current) {
return prev * current;
}, 1);
};
and to get a reference to $scope.filteredItems use this in your view
<div ng-repeat="y in (filteredItems = (x | filter:myFilter:rec))">
You could do something like this:
angular.module('myApp', [])
.controller('MyController', MyController);
function MyController($scope) {
$scope.result = 1;
$scope.recObj = {};
$scope.rec = {
a: 2,
b: 3,
c: 5,
name: 'a,b,c,d'
};
function initData() {
var dataKeysArr = $scope.rec.name.split(",");
for (var dataKey of dataKeysArr) {
if ($scope.rec.hasOwnProperty(dataKey)) {
$scope.recObj[dataKey] = $scope.rec[dataKey];
}
}
};
initData();
// Watch
$scope.$watchCollection(
"recObj",
function() {
$scope.result = 1;
for (var dataKey in $scope.recObj) {
$scope.result *= $scope.recObj[dataKey];
};
}
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MyController">
<div ng-repeat="(key, val) in recObj">
<label for="{{key}}">{{key}}</label>
<input type="number" id="{{key}}" ng-model="recObj[key]">
</div>
<div>
<input id="calc" type="number" ng-model="result" disabled>
</div>
</div>
</div>

Adding of users to dropdown list doesn't work

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%

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