adding input values from form to json object using angularjs - angularjs

am trying to add the value of input field to json object using angularjs i wrote some codes but it doesn't work, please i need help
script section
<script>
var app = angular.module("exampleApp", []);
app.controller("defaultCtrl", function ($scope, $http) {
$scope.loadData = function () {
$http.get("productData.json").then(function (response) {
console.log("Status: " + response.status);
console.log("Type: " + response.headers("content-type"));
console.log("Length: " + response.headers("content-length"));
$scope.products = response.data;
});
$scope.products = {name:'',age:'',isDead:''};
$scope.resurrect = function(item){
item.isDead = false;
};
$scope.addnew = function(){
$scope.products.mname = $scope.products.name;
$scope.products.mage = $scope.products.age;
$scope.products.misDead = $scope.products.isDead;
};
}
});
</script>
productData.json
[
{ "name": "Tommen Baratheon", "age": "23", "isDead": true },
{ "name": "Roose Bolton", "age": "32", "isDead": false },
{ "name": "Theon Greyjoy", "age": "27", "isDead": true},
{ "name": "Cersei Lannister", "age": "31", "isDead": false}
]
form section
<form>
<input type="text" placeholder="Enter Charater name" class="form- control" ng-model="products.mname">
<input type="number" placeholder="Enter Charater age" class="form-control" ng-model="products.mage">
<input type="text" placeholder="Enter True or false" class="form-control" ng-model="products.misDead">
<input type="submit" value="andNew" ng-submit="addnew()"></form>

So the first problem is that $scope.products is an array. Your markup is bound as if it's a single object though.
<form>
<div ng-repeat="p in products">
<input type="text" placeholder="Enter Charater name" class="form-control" ng-model="p.name">
<input type="number" placeholder="Enter Charater age" class="form-control" ng-model="p.age">
<input type="text" placeholder="Enter True or false" class="form-control" ng-model="p.isDead">
<input type="submit" value="andNew" ng-submit="addnew()">
</div>
</form>
The other problem was that you had bindings like products.mname, but the field is actually name. The next problem you have is you're initializing products as an object when you really should just initialize it as an empty array:
$scope.products = [];
The next problem you'll have is addnew. It needs to just push a new object on to the array:
$scope.addnew = function() {
$scope.products.push({});
};
That will cause a new div to be rendered inside the form.

Related

Reloading form does not update in AngularJS?

I am creating a form, where when the user clicks on the edit button to edit the text, it works fine. But when user clicks on the update button then reload the page it does not show the updated text after reloading the page.
Here is the plunker, that it worked but the code below does not work when page reloads. (I want to do this only with Front-End)
http://plnkr.co/edit/yyDf2SuEvefLWIK13kS4?p=preview
Here is my code.
<div class="people-view">
<h2 class="name">{{people.first}}</h2>
<h2 class="name">{{people.last}}</h2>
<span class="title">{{people.title}}</span>
<span class="date">{{people.date}} </span>
</div>
<div ng-controller="MyCtrl">
<div class="list-view">
<form>
<fieldset ng-disabled="inactive">
<legend>Basic Info</legend>
<b>First Name:</b>
<input type="text" ng-model="people.first">
<br>
<b>Last Name:</b>
<input type="text" ng-model="people.last">
<br>
<b>Email:</b>
<input type="email" ng-model="people.email">
<br>
<b>Phone:</b>
<input type="num" ng-model="people.phone">
<br>
<b>Website:</b>
<input type="text" ng-model="people.website">
<br>
<b>Education:</b>
<input type="text" ng-model="people.education">
<br>
<b>Education Year:</b>
<input type="text" ng-model="people.year">
<br>
<legend>Address</legend>
<b>Street:</b>
<input type="text" ng-model="people.street">
<br>
<b>City:</b>
<input type="text" ng-model="people.city">
<br>
<b>State:</b>
<input type="text" ng-model="people.state">
<br>
<b>Zip:</b>
<input type="text" ng-model="people.zip">
<br>
</fieldset>
<button type="button" class="edit" ng-show="inactive" ng-click="inactive = !inactive">
Edit
</button>
<button type="submit" class="submit" ng-show="!inactive" ng-click="save()">Save</button>
</form>
</div>
</div>
App.js
var app = angular.module("Portal", []);
app.controller('MyCtrl', function($scope) {
$scope.inactive = true;
$scope.save = function() {
$scope.msg = 'Data sent: '+ JSON.stringify($scope.people);
};
});
JSON file
[
{
"id": "0",
"first": "John",
"last": "Smith",
"img": "//placehold.it/100x100",
"title": "Family",
"date": "Joined 4/2/17",
"email": "jsmith#email.com",
"phone": "555-555-5555",
"website": "www.google.com",
"education": "NYU Law",
"year": "2008",
"street": "123 Main Street",
"city": "Los Angeles",
"state": "CA",
"zip": "1234567"
},
]
Controller
app.controller('PeopleController',['$scope', 'people', '$routeParams',
function($scope, people, $routeParams) {
people.success(function(data) {
$scope.people = data[$routeParams.id];
});
}]);
You can try using the prevent default handler:
ng-click="save($event)"
In your controller, you can put:
$scope.save = function (event) {
event.preventDefault();
$scope.msg = 'Data sent: '+ JSON.stringify($scope.people);
}
to make your changes permanent you have to store it to some sort of storage. files is ok but it's not the best choice. So you may consider using local storage. here is good tutorial of how to handle
local-storage. so the controller will be like
app.controller('myCtrl', ['$scope', function($scope){
$scope.people = {
"first": "John",
"last": "Smith"
}
$scope.myObject = JSON.parse(localStorage.getItem('myObject')) || {
first : $scope.people.first,
last : $scope.people.last
};
$scope.updateThingy = function(){
$scope.people.first = $scope.myObject.first;
$scope.people.last = $scope.myObject.last;
localStorage.setItem('myObject', JSON.stringify($scope.myObject));
};
}]);
here is the plunker. Good luck

Using ng-repeat with ng-model modifies wrong object

TLDR: Here's a plnkr of the issue: https://plnkr.co/edit/HfRoCgPfdoZNxmTtDLf7?p=preview
I have a form with checkboxes:
<div class="form-group">
<div class="input-group">
<div class="checkbox">
<label>
<input type="checkbox" ng-model="rental.car2go.airport.berlin"> Berlin
</label>
<br/>
<label>
<input type="checkbox" ng-model="rental.car2go.airport.hamburg"> Hamburg
</label>
<br/>
</div>
</div>
</div>
that is modifying the rental object. This is how the controller looks like:
angular.module('c2gyoApp', []).controller('c2gyoAppController', [
'$scope',
'state',
function($scope, state) {
$scope.airports = [{
"name": "Berlin",
"model": "rental.car2go.airport.berlin"
}, {
"name": "Hamburg",
"model": "rental.car2go.airport.hamburg"
}, ];
$scope.rental = state.rental;
}]).factory('state', function() {
var rental = {
car2go: {
airport: {
berlin: false,
hamburg: false
}
}
};
return {
rental: rental
};
});
Now I want to use ng-repeat:
<div class="form-group">
<div class="input-group">
<div class="checkbox">
<span ng-repeat="airport in airports">
<label>
<input type="checkbox"
ng-model="airport.model">
{{airport.name}}
</label>
<br>
</span>
</div>
</div>
</div>
With ng-repeat the form is modifying the airports object (airports[1].model=true/false and airports[2].model=true/false).
It should only use the string of that airport object(rental.car2go.airport.berlin and rental.car2go.airport.hamburg ) and modify the rental object. I'm looking for a way to pass the string to ng-model, not the airports object. How can I do this?
Edit: removed the directive, new plnkr
The JSON you are changing is:
$scope.airports = [{
"airport": "Berlin",
"model": "rental.car2go.airport.berlin"
}, {
"airport": "Hamburg",
"model": "rental.car2go.airport.hamburg"
}, ];
where `airports[0].model="rental.car2go.airport.berlin", meaning the string rental.car2go.airport.berlin. This string is replaced with TRUE or FALSE. I guess that you were expecting rental.car2go.airport.berlin to be interpreted as a structure, right? Well, it is not a structure but just a string.
Indeed as #Claies suggested I had to copy the value to the rental array. I used a ng-change function for that. New ng-repeat:
<span ng-repeat="airport in airports">
<label>
<input type="checkbox"
ng-model="airport.model"
ng-change="changeAirport(airport)">
{{airport.name}}
</label>
<br>
</span>
In the controller:
$scope.changeAirport = function(airport) {
var airportName = $filter('lowercase')(airport.name);
state.rental.car2go.airport[airportName] = airport.model;
}

Update an object inside an array inside an object in AngularJS

I'm building a client collection with the following information:
"name" : "Test client",
"email" : "test#test.com",
"position" : "Project Manger",
"contacts" : [
{
"name" : "asdf",
"email" : "asdf#adf",
"tel" : "7877877878",
"title" : "asdf"
},
{
"name" : "fdas",
"email" : "fdas#fdas",
"tel" : "7877877878",
"title" : "fdsa"
}
],
I want to be able to edit/update the contacts of the client but I'm not sure how to do so with angular since I have the form inside an ng-repeat repeating the contacts of a client.
<div ng-repeat="contact in contacts track by $index">
<label>Name</label>
<input type="tel" ng-model="contact.name">
<label>Telephone</label>
<input type="tel" ng-model="contact.tel">
<label>Email</label>
<input type="email" ng-model="contact.email">
<label>Title</label>
<input type="text" ng-model="contact.title">
<md-button ng-click="save(contact)">Save</md-button>
</div>
and my controller:
'use strict'
angular.module('myApp')
.controller('ContactsCtrl', function($scope, $mdDialog, $mdMedia, client) {
$scope.client = client;
$scope.contacts = client.contacts;
$scope.save = (contact) => {
Clients.update({_id: client._id},{
$set: {
contacts : contact
}
},function(err, data){
if(err) return console.log(err);
console.log(data + " " );
$mdDialog.hide(data);
});
}
$scope.cancel = function() {
$mdDialog.cancel();
};
$scope.hide = function() {
$mdDialog.hide();
};
});
But when I press save it replaces the array with a single object.
QUESTION
How can I update the existing objects in an array that are inside a document with a form that is inside an ng-repeat?
change html to :
<div ng-repeat="contact in contacts track by $index">
<label>Name</label>
<input type="tel" ng-model="contact.name">
<label>Telephone</label>
<input type="tel" ng-model="contact.tel">
<label>Email</label>
<input type="email" ng-model="contact.email">
<label>Title</label>
<input type="text" ng-model="contact.title">
<md-button ng-click="save($index,contact)">Save</md-button>
</div>
and save() function to
$scope.save = (index,contact) => {
Clients.update({_id: client._id},{
$set: {
contacts[index] : contact
}
},function(err, data){
if(err) return console.log(err);
console.log(data + " " );
$mdDialog.hide(data);
});
}
hope it does the trick.
Was able to do a work around but I'm not sure if this is the best option.
Just add $index when doing the save function:
<md-button ng-click="save($index, contact)">Save</md-button>
and in the controller the save function:
$scope.save = (index, contact) => {
$scope.client.contacts[index] = contact;
Clients.update({_id: client._id},{
$set: {
contacts : $scope.client.contacts
}
},function(err, data){
if(err) return console.log(err);
console.log(data + " " );
$mdDialog.hide(data);
});
}

AngularJS dynamic Form does not get valid

I have a dynamic Form in AngularJS, the input tags get replaced according to question type selected by the user. So the problem is, when user left a input tag blank which is required and switched to another type of questions, the form remains invalid(even the current form is valid).
I am adding the JsFiddle for it, you will get the idea.
HTML
<body ng-app="myApp" ng-controller="myCtrl">
<form name="myForm" novalidate>
<div><input name='name' type='text' ng-model='name' ng-required='true' placeholder='name'></div>
<div compile="myHtml"></div>
<input type="radio" ng-required='true' ng-click="addQuestion(1)" ng-model="radio" value="1"> Question 1 & 3
<input type="radio" ng-required='true' ng-click="addQuestion(2)" ng-model="radio" value="2"> Question 2 & 4
<input type="submit" name="submit" ng-click="" ng-disabled="myForm.$invalid">
</form>
</body>
Javascript
// the main (app) module
var myApp = angular.module("myApp", []);
// add a controller
myApp.controller("myCtrl", function($scope) {
$scope.name = "John Doe";
$scope.myHtml = "";
$scope.radio="1";
$scope.question1 = 1;
$scope.question2 = 2;
$scope.question4 = 4;
$scope.addQuestion = function(id) {
$scope.myHtml = "";
if(id == 1) {
$scope.myHtml += "<div><input name='question1' type='text' ng-model='question1' ng-required='true' placeholder='Question 1'></div>";
$scope.myHtml += "<div><input name='question3' type='text' ng-model='question3' ng-required='true' placeholder='Question 3'></div>";
};
if(id == 2) {
$scope.myHtml += "<div><input name='question2' type='text' ng-model='question2' ng-required='true' placeholder='Question 2'></div>";
$scope.myHtml += "<div><input name='question4' type='text' ng-model='question4' ng-required='true' placeholder='Question 4'></div>";
};
};
$scope.addQuestion(1);
});
// add a directive
myApp.directive('compile', ['$compile', function ($compile) {
return function(scope, element, attrs) {
scope.$watch(
function(scope) {
// watch the 'compile' expression for changes
return scope.$eval(attrs.compile);
},
function(value) {
// when the 'compile' expression changes
// assign it into the current DOM
element.html(value);
// compile the new DOM and link it to the current
// scope.
// NOTE: we only compile .childNodes so that
// we don't get into infinite loop compiling ourselves
$compile(element.contents())(scope);
}
);
};
}]);
Server JSON for question
$scope.fields = [{
"caption": "Gender",
"questionType": "RADIO",
"optionValues": ["Male", "Female"],
"fieldPriority": "REQUIRED"
}, {
"caption": "City",
"questionType": "TEXT",
"optionValues": "",
"fieldPriority": "REQUIRED"
}, {
"caption": "Address",
"questionType": "PARAGRAPH_TEXT",
"optionValues": "",
"fieldPriority": "REQUIRED"
}, {
"caption": "Nationality",
"questionType": "LIST",
"optionValues": ["Indian", "American"],
"fieldPriority": "REQUIRED"
}, {
"caption": "Tea/Coffee",
"questionType": "CHECKBOX",
"optionValues": ["Tea", "Coffee"],
"fieldPriority": "REQUIRED"
}];
Thanks
Do not store plane html in controller. Just use ng-if or ng-show to handle your logic.
I'd refactor your code to use ng-include instead of compiling html from controller which is completely bad pattern in angularjs.
You could inject the template on basis of radio value ng-model
<body ng-app="myApp" ng-controller="myCtrl">
<form name="myForm" novalidate>
<div>
<input name='name' type='text' ng-model='name' ng-required='true' placeholder='name'/>
</div>
<div ng-include="'question-set-'+radio +'.html'"></div>
<input type="radio" ng-required='true' ng-click="addQuestion(1)" ng-model="radio" value="1" />Question 1 & 3
<input type="radio" ng-required='true' ng-click="addQuestion(2)" ng-model="radio" value="2" />Question 2 & 4
<input type="submit" name="submit" ng-click="" ng-disabled="myForm.$invalid">
</form>
</body>
<script type="text/ng-template" id="question-set-1.html">
<div> <input name = 'question1' type='text' ng-model = 'question1' ng-required = 'true' placeholder = 'Question 1' /> </div>
<div><input name='question3' type='text' ng-model='question3' ng-required='true' placeholder='Question 3'/> </div>
</script>
<script type="text/ng-template" id="question-set-2.html">
<div><input name ='question2' type ='text' ng-model='question2' ng-required = 'true' placeholder = 'Question 2' /> </div>
<div><input name='question4' type='text' ng-model='question4' ng-required='true' placeholder='Question 4'/> </div>
</script>
Working Fiddle

UI Bootstrap Typeahead not returning async values

I am trying to do an autocomplete search using UI Bootstrap Typeahead to select a category from a database.
I have set up an example database with 4 categories, the final one will contain more than a thousand categories.
When I start typing, the search results return 4 rows (so something must be working, because I tried to change the number of rows in the DB and the search result mirrors the total number of rows) but with no value. However, it doesn't matter what I write so it doesn't seem to be matching.
HTML
<input class="form-control" type="text" name="category" id="category" placeholder="Search..." ng-model="asyncSelected" typeahead="name for name in getCdOnCat($viewValue)" typeahead-loading="loadingLocations" required>
controller.js
//Typeahead: Category Search
$scope.getCdOnCat = function (searchVal) {
return dataFactory.getCdOnCategory(searchVal, globalVal_accessToken, globalVal_storeId).then(function (response) {
console.log(response.data.categories);
return response.data.categories;
}, function (error) {
console.log('Error: dataFactory.getCdOnCategory');
});
};
service.js
app.factory("dataFactory", function ($http) {
var factory = {};
factory.getCdOnCategory = function (searchVal, accessToken, storeId) {
return $http.get('data/getCdOnCategory.aspx?searchVal=' + searchVal + '&accessToken=' + accessToken + '&storeId=' + storeId)
};
return factory;
});
JSON
{ "categories":[
{ "name": "Clothes" },
{ "name": "Cypress" },
{ "name": "Citrus" },
{ "name": "Cats" }
] }
Please see here http://plnkr.co/edit/F4n1kNOHfZ9f3Zz63x2P?p=preview
change
<input class="form-control" type="text" name="category" id="category"
placeholder="Search..." ng-model="asyncSelected"
typeahead="name for name in getCdOnCat($viewValue)" typeahead-loading="loadingLocations"
required>
to
<input class="form-control" type="text" name="category" id="category"
placeholder="Search..." ng-model="asyncSelected"
typeahead="obj.name for obj in getCdOnCat($viewValue)" typeahead-loading="loadingLocations"
required>

Resources