How to push an object array into an scop array? - angularjs

In angular js How can I push an object array into an array.
Here is my code
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body ng-app="myApp" ng-controller="myCtrl">
<h1 ng-repeat="x in records">{{x.Class}}
</h1>
<div ng-repeat="s in records.students">{{s.name}}</div>
<input ng-model="formdata.name" type="text" />
<input type="button" value="Save" ng-click="saveName(formdata)">
<script>
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.records = [{"Class":"Class 8"}];
$scope.saveName = function(name)
{
$scope.records.students.push({"name":name});
}
});
</script>
</body>
</html>
how can I push into $scope.records.students here $scope.records is an array.
what mistake I am doing I am getting "Cannot read property 'push' of undefined"

Your records property on $scope has no property called students. Therefore, $scope.records.students is undefined. Undefined doesn't have any methods available. You should make sure students exists before pushing.
Also, be aware the ngModel passes by reference. In your original code, the {{s.name}} list will only ever show the text in the input because each element in students points towards the same underlying reference. You should dereference the string that saveName receives. I've done so in the code below, but try playing with it so you can see how it works.
Updated code:
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body ng-app="myApp" ng-controller="myCtrl">
<h1 ng-repeat="x in records">{{x.Class}}
</h1>
<div ng-repeat="s in records.students">{{s.name}}</div>
<input ng-model="formdata.name" type="text" />
<input type="button" value="Save" ng-click="saveName(formdata)">
<script>
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.records = [{"Class":"Class 8"}];
$scope.saveName = function(name)
{
// Also, you need to derefence the object
// this is a quick and dirty way, try removing it and see
// what happens
var deRefName = JSON.stringify(name);
// Checks for the existence of students, if it doesn't exist
// sets students to an empty array
if (!($scope.records.students)) {
$scope.records.students = [];
}
$scope.records.students.push({"name":deRefName});
}
});
</script>
</body>
</html>

As the error denotes, there is no way you can access records.students since its an array, not an object.
You need to have records as either an object and inside it student as an array.
then you should be able to access $scope.records.students.
or use $scope.records as array and use index to access the particular object of it.

Related

angularJS what's a good way to put dictionary in input

I have a dictionary of data in the controller and I'm displaying it using ng-repeat. The key is the Title and the value is placed as the value field of an input. I want the user to be able to edit the values and then submit the form. What's the best way I can handle all the input? I've tried ng-model but I can't change the values of the dictionary directly so I'm leaning towards making another dictionary to store the new data. That doesn't seem very efficient though so I'm wondering if there's a better way.
edit: I have this interface and add some values.
export interface Iint {
[title: string] : string;
}
this is in the constructor
this.hashMap : Iint = {};
this.hashMap["Next Title"] = "data";
this.hashMap["Next Value"] = "more data;
In the html I want each of the values (data, more data) to appear in it's own input text box where the user can edit and change the values in the dictionary. I need validation and other things before the user can save and update the data so I'm unsure of if I should be making a duplicate array.
Check this example out. I implemented it in Angular v1 before you edited your answer.
https://plnkr.co/edit/9Y33BDQTngPZx2Vpx5Zz?p=preview
script.js
var app = angular.module('myApp',[]);
app.controller('MyCtrl', ['$scope', function($scope) {
$scope.dict = {
"Title1" : "Hello World !",
"Title2" : "Beautiful day",
"Title3" : "How about that!?"
};
$scope.submitForm = function() {
console.log($scope.dict);
alert(JSON.stringify($scope.dict));
};
}]);
index.html:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="myApp">
<h1>Dictionary Inputs</h1>
<div ng-controller="MyCtrl">
<form name="myForm" ng-submit="submitForm()">
<ul>
<li ng-repeat="(key,val) in dict">
{{key}} : <input type="text" ng-model="$parent.dict[key]">
</li>
</ul>
<button type="submit"> Submit</button>
</form>
<br/>
<div>
$scope.dict : {{dict}}
</div>
</div>
</body>
</html>
Implementing it in Angular v2 might be on similar lines.
It is possible to get ngRepeat to iterate over the properties of an object using the following syntax:
<div ng-repeat="(key, value) in myObj"> ... </div>
Reference: https://docs.angularjs.org/api/ng/directive/ngRepeat#iterating-over-object-properties

Lose the focus after inserting a letter

I have written a script which represent a json data in 2 ways: JSBin
<!DOCTYPE html>
<html>
<head>
<script src="https://handsontable.github.io/ngHandsontable/node_modules/angular/angular.js"></script>
</head>
<body ng-app="app">
<div ng-controller="Ctrl">
GUI:
<div ng-repeat="item in data">
<input ng-model="item.val">
</div>
<br><br><br>
Textarea:<br>
<textarea rows=10 cols=20 ng-model="dataString"></textarea>
</div>
<script>
var app = angular.module('app', []);
app.controller('Ctrl', ['$scope', '$filter', function($scope, $filter) {
$scope.data = [{val: "1"}, {val: "2"}];
$scope.$watch('data', function(data_new) {
$scope.dataString = $filter('json')(data_new);
}, true);
$scope.$watch('dataString', function(dataString_new) {
$scope.data = JSON.parse(dataString_new);
}, true);
}]);
</script>
</body>
</html>
Thus, modifying the value in GUI will change the string in the textarea (because of $watch('data'); and modifying the string in the textarea will change the GUI (because of $watch('dataString')).
However, the problem is that when we change the value in GUI, we lose the focus after inserting a letter.
Does anyone know how to amend this?
So the problem is that you are iterating over an array (ng-repeat) and changeing the items of the array. The items are removed from the DOM and new one are inserted because they are strings and thereby compared by value. This makes you loose focus.
It's pretty simple to fix though. Just track by index as the objects are in identical order.
Change:
<div ng-repeat="item in data">
To:
<div ng-repeat="item in data track by $index">

How to show the ID of array objects?

I was wondering how to print ids of items inside an array.
I have and array called localData, with a list of objects inside. Every object is a mini array of 3 strings.
In my ng-repeat when i set {{items in array}} it prints the content and not the id. How can i print only ids?
localData = {"-KRFLxEmRoS7M9gKDXVE":{"postBody":"1) remove lag 2) add animations",
"postTitle":"Top Title $$$","userName":"[Admin]"},
"-KRFM6Jm2wQemtl878Ur":"postBody":"Annanana","postTitle":"Ananaj",
"userName":"[Admin]"},"-KRFM7rcEe5K5PXkb29v":{"postBody":"Abshhsua","postTitle":"Ababjsjs","userName":"[Admin]"},
"-KRFM96LtmaXRTnUXJoV":{"postBody":"Gabshsysus","postTitle":"Bshshshshs","userName":"[Admin]"},
"-KRFMAnqecr85xUcOCuw":{"postBody":"Sbsbshshsusudu","postTitle":"Ushhshshs","userName":"[Admin]"},
"-KRFMCkO3JdhA_0MlwwM":{"postBody":"Hshshshs","postTitle":"Sjjsjsjs","userName":"[Admin]"},
"-KRFMLtDJsO0fGYA9JEO":{"postBody":"Fake",
"postTitle":"OMG EPICCCCCCOOOO","userName":"[Admin]"},
"-KRFMQBwIbK6s5lVMlbW":{"postBody":"Asdrobololo","postTitle":"Asdrubale","userName":"[Admin]"},
"-KRI7TVGM0U5emvwD0i7":{"postBody":"Htrsdvgh","postTitle":"Uutfcbuj","userName":"[Admin]"},"-KRITPhL8m-qCCO9y4vY":
{"postBody":"Iiiiiiiwwwwww","postTitle":"Jjjdhd","userName":"[Admin]"}}
angular.module('myapp', [])
.controller('PostsCtrl', function($scope) {
var object={"nm_questionario":{"isEmpty":"MSGE1 - Nome do Questionário"},"ds_questionario":{"isEmpty":"MSGE1 - Descrição do Questionário"},"dt_inicio_vigencia":{"isEmpty":"MSGE1 - Data de Vigência"}};
$scope.items = [];
angular.forEach(object, function (value, key) {
$scope.items.push(key);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myapp" ng-controller="PostsCtrl">
<div ng-repeat="item in items">
{{item}}
</div>
</div>
Store the local data like below to get the id easily. Try this below.
angular.module('myapp', [])
.controller('PostsCtrl', function($scope) {
var accountservice=[{"id":"1","title":"Savings Account","services":[{"types":"ATM card request"},{"types":"loan request"}]},
{"id":"2","title":"Current Account","services":[{"types":"cheque book request"},{"types":"ATM card request"}]},
{"id":"3","title":"Demat Account","services":[{"types":"loan request"},{"types":"ATM card request"}]}];
$scope.accountservices = accountservice;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myapp" ng-controller="PostsCtrl">
<div ng-repeat="(key,value) in accountservices">
<p>{{value.id}}</p>
<ul><li ng-repeat="account in value.services">{{account.types}}</li></ul>
</div>
</div>

Variable in one controller is being affected by the same name variable in another controller

I'm in a project that uses angularjs and rails. So, i'm using this library too:
https://github.com/FineLinePrototyping/angularjs-rails-resource
Well, when i'm using the controller as syntax from angularjs, some strange behaviour is happening. You can see that in this plunker example:
http://plnkr.co/edit/i4Ohhh8llS7WN68sLX5q?p=preview
The promise object returned by the remote call in first controller using the angularjs-rails-resource library in some way is setting the instance variable that belongs to the second controller. I don't know if it is a bug in the library, or an angular behaviour that i should know. Anyway, is clearly an undesirable behaviour.
Here is the same plunker code (index.html):
<!doctype html>
<html ng-app="Demo">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.js"></script>
<script src="https://rawgit.com/FineLinePrototyping/dist-angularjs-rails-resource/master/angularjs-rails-resource.min.js"></script>
<script src="example.js"></script>
</head>
<body>
<div ng-controller="Controller1 as ctrl1">
<form>
<label>should appear first remote</label>
<input type="text" ng-model="ctrl1.remote.name"/><br>
<label>should appear first local</label>
<input type="text" ng-model="ctrl1.local.name"/>
</form>
</div>
<br>
<div ng-controller="Controller2 as ctrl2">
<form>
<label>should appear second local</label>
<input type="text" ng-model="ctrl2.remote.name"/><br>
<label>should appear second local</label>
<input type="text" ng-model="ctrl2.local.name"/>
</form>
</div>
</body>
</html>
My angularjs code (example.js):
angular.module('Demo', ['rails']);
angular.module('Demo').controller('Controller1', ['$scope', 'Remote', function($scope, Remote) {
ctrl = this;
ctrl.remote = {};
Remote.get().then(function(remote) {
ctrl.remote = remote;
});
ctrl.local = {};
ctrl.local.name = "first local";
}]);
angular.module('Demo').controller('Controller2', ['$scope', function($scope) {
ctrl = this;
// SAME VARIABLE NAME
// WILL RECEIVE VALUE FROM REMOTE CALL ON FIRST CONTROLLER!!!
ctrl.remote = {};
ctrl.remote.name = "second local";
// SAME VARIABLE NAME
ctrl.local = {};
ctrl.local.name = "second local";
}])
angular.module('Demo').factory('Remote', [
'railsResourceFactory',
'railsSerializer',
function (railsResourceFactory, railsSerializer) {
return railsResourceFactory({
url:'clients.json',
name: 'remote',
})
}]
);
clients.json
{
"name":"first remote"
}
Any ideias how fix this without having to change variable names to avoid conflict? Because that way we will just mask the problem.
I report the problem to angularjs-rails-resource library but no answer until now.
You need to use var when declaring your variables, otherwise they're global.
Use
var ctrl = this; instead of just ctrl = this;
Also, 'use strict' is a nice thing to use(and it helps in these situations)

Consuming REST service using AngularJS

I have a REST Service written in Java which returns an array of data in JSON like this:
[{"key":"London","value":"51.30"}]
Now I'm trying code an AngularJS REST clients using the AJS documentation. So far I've been able to invoke the REST service (I can see from the server logs) yet nothing is printed in the HTML page.
Here is my code:
<!doctype html>
<html >
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular-resource.js"></script>
<script language="javascript">
angular.module('myApp',['ngResource']);
function Ctrl($scope,$resource) {
var Geonames = $resource(
'http://localhost:8080/rest-application/rest/json', {
}, {
query: { method: 'GET', isArray: true },
create: { method: 'POST' }
}
);
$scope.objs = Geonames.query();
};
Ctrl.$inject = ['$scope','$resource'];
</script>
</head>
<body >
<div ng-app="myApp">
<div ng-controller="Ctrl">
{{objs.key}} - {{objs.value}}
</div>
</div>
</body>
</html>
I have tried this example with several small variants taken from tutorials yet it is still not working. Any help ?
Thanks!
What you get back from query() is an array so you should loop over it with ng-repeat
<div ng-app="myApp">
<div ng-controller="Ctrl">
<ul>
<li ng-repeat="obj in objs">{{obj.key}} - {{obj.value}}</li>
</ul>
</div>
</div>
First of all, let's organize your code a bit:
var app = angular.module('myApp',['ngResource']);
// Controllers get their dependencies injected, as long as you don't minify your code and lose variable names.
app.controller('Ctrl', function($scope, $resource) {
$scope.objs = []; // We initialize the variable for the view not to break.
// For the query example, you don't need to define the method explicitly, it is already defined for you.
var Geonames = $resource('http://localhost:8080/rest-application/rest/json');
// Resource methods use promises, read more about them here: http://docs.angularjs.org/api/ng/service/$q
Geonames.query({}, function(arrayResult) {
$scope.objs = arrayResult;
});
});
You have to adjust your html code with an ng-repeat directive to handle each item of your array:
<body>
<div ng-app="myApp">
<div ng-controller="Ctrl">
<!-- object is a reference for each item in the $scope.objs array-->
<span ng-repeat="object in objs">
{{object.key}} - {{object.value}}
</span>
</div>
</div>
</body>

Resources