Cannot get input form items to populate table - angularjs

I'm currently building a simple little app to as I learn angular.js, and am having a bit of trouble populating a table with the data keyed in by the user. I'm receiving an error:
Cannot read property 'push' of undefined
The JS is below:
var app = angular.module('yardApp', []);
app.controller('mainController', function($http){
var yardSale = this;
yardSale.forSale = [];
yardSale.login = function(){
yardSale.loggedIn = true;
$http({
method: "POST",
url: "/user",
data: { username:yardSale.username }
}).then(function(result){
console.log(result.data);
yardSale.userId = result.data._id;
yardSale.userId = result.data.username;
});
};
yardSale.addItem = function(){
console.log(yardSale.item.product);
yardSale.items.push(yardSale.item);
// yardSale.item = {};
};
}):
The html looks like:
<div>
<h1>Welcome to the Yard Sale!!</h1>
<h2 ng-hide="yardSale.loggedIn"> Plese login to get started.</h2>
<h2 ng-show="yardSale.loggedIn">Welcome {{ yardSale.username }}!</h2>
<h2 ng-show="yardSale.loggedIn">Have anything you'd like to sell?</h2>
<h3 ng-show="yardSale.loggedIn">Please, list it here!</h3>
</div>
<form ng-submit="yardSale.login()" ng-hide="yardSale.loggedIn">
<input type="text" placeholder="Please enter a username" ng-model="yardSale.username">
<input class="btn btn-primary" type="submit" value="login">
</form>
<div class="row" ng-show="yardSale.loggedIn">
<form ng-submit="yardSale.addItem()">
<input type="text" placeholder="Item for Sale" ng-model="yardSale.item.product">
<input type="text" placeholder="Price you'd like" ng-model="yardSale.item.price">
<input type="date" placeholder="Date Listed" ng-model="yardSale.item.date">
<input class="btn btn-primary" type="submit" value="add">
</form>
<table class="col-md-6 col-md-offset-4 table-bordered">
<thead>
<tr>
<th>Item</th>
<th>Price</th>
<th>Date Listed</th>
</tr>
</thead>
<tbody>
<tr ng-repeat=" item in yardSale.items">
<td>{{ item.product }}</td>
<td>{{ item.price | currency }}</td>
<td>{{ item.date | date }}</td>
</tr>
</tbody>
</table>
</div>
i can console log yardsale.item.product and see what I enter, but cannot populate it to the table

You get the error cannot read property push of undefined because of your variable called items. Try to do add yardSale.items = [] after this line of code aka your constructor.
var yardSale = this;
yardSale.forSale = [];
yardSale.items = [];

cannot read property push of undefined
This error appears when you are trying to access the value of a variable which is not declared. In this case yardSale.items is never declared. The compiler should be made known of such an attribute exists for the object yardSale, also whether that attribute (ie items) is an object or an array. Hence the answer by #amcpanaligan is a correct solution. you need to declare it as:
yardSale.items = [];
The try:
yardSale.items.push(yardSale.item);
It will work.

Related

angularjs http not working in mvc when using get list of data

I want simply fetch the list of items using angular js .I am using angular code and using $http. but its not working. I hit on action method and try to return json. but when i am trying it. it return full json on view.
#section scripts{
<script src="~/Scripts/ang.js"></script>
}
<div ng-app="StudentApp" class="container">
<br/>
<br/>
<input type="text" placeholder="Search Student" ng-model="searchStudent" />
<br />
<div ng-controller="StudentController">
<table class="table" ng-init="initData()">
<tr ng-repeat="r in data | filter : searchStudent" >
<td>{{ r.Col_Title }}</td>
<td>{{ r.Col_Descrp }}</td>
</tr>
<table>
</div>
</div>
public ActionResult GetCollections()
{
var lst = eShoppingEntitiesContetxt.Collections.Where(s => s.IsActive == true).ToList();
var result = JsonConvert.SerializeObject(lst, new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
return Json(result, JsonRequestBehavior.AllowGet);
// return View();
}
var myApp = angular.module('StudentApp', []);
myApp.controller('StudentController', function ($scope, $http) {
$http.get('/User/GetCollections') // added an '/' along with deleting Controller portion
.then(function (response) {
$scope.data = response.data
})})
<div ng-app="StudentApp" class="container">
<br/>
<br/>
<input type="text" placeholder="Search Student" ng-model="searchStudent" />
<br />
<div ng-controller="StudentController">
<table class="table">
<tr ng-repeat="r in data | filter : searchStudent" >
<td>{{ r.name }}</td>
<td>{{ r.country }}</td>
</tr>
<table>
</div>
</div>
Try this:
var myApp = angular.module('StudentApp', []);
myApp.controller('StudentController', function($scope, $http) {
$scope.initData = function() {
$http.get('/User/GetCollections') // added an '/' along with deleting Controller portion
.then(function(response) {
$scope.data = response.data;
});
}
});
In your view (notice the ng-init="initData()" in the table)
<div ng-app="StudentApp" class="container">
<br/>
<br/>
<input type="text" placeholder="Search Student" ng-model="searchStudent" />
<br />
<div ng-controller="StudentController">
<table class="table" ng-init="initData()">
<tr ng-repeat="r in data | filter : searchStudent" >
<td>{{ r.name }}</td>
<td>{{ r.country }}</td>
</tr>
<table>
</div>
As your question says : it return full json on view....
So I hope you forgot to convert your stringfy json to object. Like :
$scope.data = angular.fromJson(response.data);
Update
Your not calling REST api method, rather MVC controller, which will ofcourse render view with json.
you need to create a REST API method. like :
[Route("User/GetCollections")]
public JsonResult GetCollections()
{
// compute your data.
return new Json(data, JsonRequestBehavior.AllowGet);
}
and remove ng-init="initData()" from html. Since your controller will bind $scope.data.

how to write function to target specific variable for ng disable that inside ng repeat?

I'm trying to build todo list app in angular. When you add new item, it will add to input box(by default, i set it to disabled) inside the table and also add Edit link next to that input. Once i click on the Edit, the input box will enable. ( i got it working with this code (Edit).
My question is how to replace ng-click="editable=!editable" with ng-click="edit()". I tried to write that Edit function, but i can't get it to work. Please help.
My code on jsfiddle
Thanks so much.
<body ng-app="shoppingList">
<div ng-controller="mainController">
<h1>My Shopping List</h1>
<form class="form-inline" ng-submit="addItem()">
<div class="form-group">
<input type="text" ng-model="newItem">
</div>
<input type="submit" value="Add">
</form>
<div>
<table>
<thead>
<tr>
<th>Item</th>
<th>Edit</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in items track by $index">
<td><input ng-disabled="!editable" type="text" value="{{item}}"></td>
<td ng-click="editable=!editable">Edit</td>
</tr>
</tbody>
</table>
</div>
</div>
<script>
(function(){
var app = angular.module('shoppingList',[]);
app.controller('mainController',function($scope){
$scope.items=[];
$scope.addItem = function(){
$scope.items.push($scope.newItem);
};
$scope.edit = function(){
// i need to move editable=!editable into this function
// but i don't know how to do that
}
});
}());
</script>
You could save the editable property of the todo item, and then us it like this.
$scope.addItem = function(){
$scope.items.push({text: $scope.newItem,editable:false});
};
$scope.edit = function(item){
item.editable = !item.editable;
console.log(item)
}
$scope.save = function(item){
console.log("saved")
item.editable = !item.editable;
}
html
<tr ng-repeat="item in items track by $index">
<td><input ng-disabled="!item.editable" ng-blur="save(item)" type="text" value="{{item.text}}"></td>
<td ng-click="edit(item)">Edit</td>
</tr>
I think this is simplest one, but there is always a better approach. Let us know. What is ngBlur

Update row in angular-smart-table

In my app i list users in a table via angular smart table. Now i would like to update a record once i modified it. I can't find any function with which i can change the user in my rowCollection so my list view reflects those changes directly.
This is my Service to receive my users from the API
services.factory('Users', function($resource) {
return $resource('/api/v1.0.0/users/:id', {id: '#id'}, {
update: {
method: 'PUT'
}
});
});
This is my List Controller to get the data from my factory. It also has the delete function. The delete function works fine - it just removes one index from the usersRowCollection. The API removes it from the DB.
app.controller('UsersCtrl', ['$scope', '$resource', 'Users',
function ($scope, $resource, Users) {
// Defines how many items per page
$scope.itemsByPage = 10;
// Create a reference object of usersRowCollection for smart table
$scope.usersRowCollection = Users.query();
$scope.usersDisplayedCollection = [].concat($scope.usersRowCollection);
/**
* Function to send a DELETE request to the API
* and to remove the row from the table
* #param user The row item
*/
$scope.deleteUser = function (user) {
// Send request to the API
user.$delete(function () {
// Remove this line from the table
var index = $scope.usersRowCollection.indexOf(user);
if (index !== -1) {
$scope.usersRowCollection.splice(index, 1);
}
})
}
}]);
This is my edit controller where i try to make the magic happen. the $scope.user.$update() function sends the changed data to the API - now i just need to get the changes reflected in my users list to which i redirect via $state.go('app.users.list') (ui-router)
app.controller('UsersEditCtrl', ['$scope', '$state', '$stateParams', 'Users',
function ($scope, $state, $stateParams, Users) {
$scope.updateUser = function () {
$scope.user.$update(function () {
$state.go('app.users.list');
//console.log($scope.user);
//console.log($scope.usersRowCollection);
//var index = $scope.usersRowCollection.indexOf($scope.user);
//console.log($scope.user.id);
// Remove this line from the table
var index = $scope.usersRowCollection.indexOf($scope.user);
if (index !== -1) {
$scope.usersRowCollection.splice(index, 1);
}
//$scope.user = Users.get({id: $scope.user.id});
//$scope.usersRowCollection.update();
// todo Update the changed entry in the table
});
};
// Loads the users json data from the REST Api
$scope.loadUser = function () {
//console.log('loadUser');
$scope.user = Users.get({id: $stateParams.id});
};
$scope.loadUser();
}]);
Thats my HTML - as you can see i use the st-safe-src attribute. If i understood correctly, it should recognice the changes and reflect them automatically.
<table st-table="usersDisplayedCollection" st-safe-src="usersRowCollection" class="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>NAME</th>
<th>EMAIL</th>
<th>ACTIVE</th>
<th>CREATED_AT</th>
<th>Aktionen</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="user in usersDisplayedCollection">
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.email }}</td>
<td>{{ user.active }}</td>
<td>{{ user.created_at }}</td>
<td>
<button type="button" confirm-button="deleteUser(user);" confirm-message="Wirklich löschen?"
class="btn btn-sm btn-danger">
<i class="fa fa-times"></i> Delete
</button>
<a href="#" ui-sref="app.users.edit({id:user.id})" class="btn btn-sm btn-warning">
<i class="fa fa-pencil"></i> Edit
</a>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="7" class="text-center">
<div st-pagination="" st-items-by-page="itemsByPage" st-displayed-pages="7"></div>
</td>
</tr>
</tfoot>
</table>
Edit form:
<form class="form-horizontal" role="form" ng-submit="updateUser()">
<div class="form-group">
<label>ID</label>
<input type="text" disabled="disabled" class="form-control" value="{{ user.id }}">
</div>
<div class="form-group">
<label for="name">NAME</label>
<input type="text" ng-model="user.name" class="form-control" id="name" placeholder="YOUR NAME">
</div>
<div class="form-group">
<label for="email">E-MAIL</label>
<input type="email" ng-model="user.email" class="form-control" id="email" placeholder="YOUR EMAIL">
</div>
<div class="radio">
<label>
<input type="radio" ng-model="user.active" name="active" id="active" value="1">
ACTIVE
</label>
<label>
<input type="radio" ng-model="user.active" name="active" id="inactive" value="0">
INACTIVE
</label>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
ABBRECHEN
<button type="submit" class="btn btn-default">SPEICHERN</button>
</div>
</div>
</form>
So, how can i reflect the changes i do in my form view directly after saving in my list view?

How to delete row from table in angularjs

Now I need to delete row(s) depends on it is selected or not. But how can I access $index in the control for each selected row?
my code is here:
<div ng-app="appTable">
<div ng-controller="Allocation">
<button ng-click="add()"> Add </button>
<button ng-click="remove()">remove</button>
<table>
<th>
<td>S.No</td>
<td>Name</td>
<td>Dept</td>
</th>
<tr ng-repeat="data in dataList">
<td><input type="checkbox" ng-model="delete"/>{{$index}}</td>
<td> <input type="text" ng-model="data.name"/></td>
<td><input type="text" ng-model="data.dept"/></td>
</tr>
</table>
</div>
</div>
var app = angular.module("appTable",[]);
app.controller("Allocation",function($scope) {
$scope.dataList = [{name:'lin',dept:'b'},{name:'test',dept:'aaa'}];
$scope.add = function(){
var data = {};
data.name ='' ;
data.dept ='';
$scope.dataList.push(data);
}
var deletes=[];
$scope.delete=false;
$scope.remove = function(){
console.log(deletes);
angular.forEach($scope.delete,function(v){
if(v==true){
deletes.push($index);*How can I get the $index for selected row*
console.log(deletes);
}
});
angular.forEach(deletes,function(v,k){
$scope.dataList.splice(v, 1);
})
}
});
Now I can add the row which match the requirement, but my issue is user have to check the checkedbox in the row which they want to delete and then click delete button to delete them. for example, they can check the first and third row to delete and only keep second row.
<div ng-app="appTable">
<div ng-controller="Allocation">
<button ng-click="add()"> Add </button>
<button ng-click="remove()">remove</button>
<table>
<th>
<td>S.No</td>
<td>Name</td>
<td>Dept</td>
</th>
<tr ng-repeat="data in dataList">
<td><input type="checkbox" ng-model="data.isDelete"/>{{$index}}</td>
<td> <input type="text" ng-model="data.name"/></td>
<td><input type="text" ng-model="data.dept"/></td>
</tr>
</table>
</div>
</div>
var app = angular.module("appTable",[]);
app.controller("Allocation",function($scope) {
$scope.dataList = [{name:'lin',dept:'b'},{name:'test',dept:'aaa'}];
$scope.add = function(){
var data = {};
data.name ='' ;
data.dept ='';
$scope.dataList.push(data);
};
$scope.remove = function(){
var newDataList=[];
angular.forEach($scope.dataList,function(v){
if(!v.isDelete){
newDataList.push(v);
}
}); $scope.dataList=newDataList;
};
});
https://jsfiddle.net/9qttf7ph/
You might need to add the following in your ng-repeat directive :
<tr ng-repeat="data in dataList track by $index">
and then use $index for deletion.
you can get more informations about this here from the official angular documentation.
Replace
<input type="checkbox" ng-model="delete"/>
by
<input type="checkbox" ng-model="data.toBeDeleted"/>
Then, on the click of the button, remove all the data which have a truthy toBeDeleted attribute from the array.

Edit Ng-Repeat inline with REST API

I have been at this for awhile now but in short I am making a UI that allows our users to modify a MySQL DB using an Angular frontend and Slim PHP to serve up the REST.
I continue to get an error stating that 'firstName' is not defined as a column and I cant seem to figure out why. I believe it has something to do with the way the ng-repeat works and how I can assign / call objects inside of it but I am stuck!
Here is the HTML, App.js and index.php - The code is a little hacked up but I want to edit the rows in-line.
Any knowledge is much appreciated as I have just started using Angular and REST this year!
List.html
<div class="row">
<div class="col-lg-12">
<table class="table table-hover">
<thead>
<tr>
<th>Id</th>
<th>First Name</th>
<th>Last Name</th>
<th>Address 1</th>
<th>Address 2</th>
<th>City</th>
<th>State</th>
<th>Zip</th>
<th class="text-center">Edit</th>
</tr>
</thead>
<tbody ng-repeat="referral in referrals | filter:query | limitTo:limitBy | orderBy:lastName">
<tr >
<td>{{referral.ID}}</td>
<td>
<!-- <span id="firstName" data-ng-hide="editMode">{{referral.firstName}}</span>-->
<span data-ng-hide="editMode">{{referral.firstName}}</span>
<input type="text" data-ng-show="editMode" ng-model="referral.firstName"/>
</td>
<td>
<span data-ng-hide="editMode">{{referral.lastName}}</span>
<input type="text" data-ng-show="editMode" ng-model="referral.lastName"/>
</td>
<td>
<span data-ng-hide="editMode">{{referral.address1}}</span>
<input type="text" data-ng-show="editMode" data-ng-model="referral.address1"/>
</td>
<td>
<span data-ng-hide="editMode">{{referral.address2}}</span>
<input type="text" data-ng-show="editMode" data-ng-model="referral.address2"/>
</td>
<td>
<span data-ng-hide="editMode">{{referral.city}}</span>
<input type="text" data-ng-show="editMode" data-ng-model="referral.city"/>
</td>
<td>
<span data-ng-hide="editMode">{{referral.state}}</span>
<input type="text" data-ng-show="editMode" data-ng-model="referral.state"/>
</td>
<td>
<span data-ng-hide="editMode">{{referral.zipCode}}</span>
<input type="text" data-ng-show="editMode" data-ng-model="referral.zipCode"/>
</td>
<td class="text-center">
<button type="submit" data-ng-hide="editMode" data-ng-click="editMode = true; editAppKey(entry)" class="btn btn-default">Edit</button>
<button type="submit" data-ng-show="editMode" data-ng-click="editMode = false; saveField(referral)" class="btn btn-default">Save</button>
<button type="submit" data-ng-show="editMode" data-ng-click="editMode = false; cancel()" class="btn btn-default">Cancel</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
App.js
app.controller('viewController', function($resource, $scope, $location, $route, $routeParams) {
$scope.title = 'Endo Admin';
$scope.query = {};
$scope.queryBy = 'lastName';
$scope.limitBy = '50';
var Referrals = $resource('http://pdgrosit02v/endoAdmin/app/api/referrals');
$scope.referrals = Referrals.query();
$scope.newField = {};
$scope.editing = false;
$scope.editAppKey = function(field) {
$scope.editing = $scope.referrals.indexOf(field);
$scope.newField = angular.copy(field);
}
$scope.saveField = function(index) {
// if ($scope.editing !== false) {
// var Referral = $resource(('http://pdgrosit02v/endoAdmin/app/api/referral/'+ index.ID));
//
// $scope.referral = Referral.get();
//
$scope.referral = $scope.newField;
// $scope.editing = false;
var ReferralPut = $resource(('http://pdgrosit02v/endoAdmin/app/api/referral/'+ index.ID), {}, { update: { method: 'PUT'}} );
ReferralPut.update($scope.referral, function() {
// success
$location.path('/endoadmin');
}, function() {
// error
console.log(error);
});
};
});
index.php
<?php
require 'Slim/Slim.php';
\Slim\Slim::registerAutoloader();
use Slim\Slim;
$app = new Slim();
$app->get('/referrals', 'getReferrals');
$app->get('/referral/:id', 'getReferral');
$app->put('/referral/:id', 'updateReferral');
$app->run();
function updateReferral($id) {
$referral = Slim::getInstance()->request()->getBody();
$data = json_decode($referral, true);
$sql = "UPDATE endo_referral SET firstName=:first_Name, lastName=:last_Name WHERE ID=$id";
try {
$db = getConnection();
$stmt = $db->prepare($sql);
$stmt->bindValue(":first_Name", $data['firstName']);
$stmt->bindValue(":last_Name", $data['lastName']);
$stmt->execute();
$db = null;
echo json_encode($data);
} catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
In the $scope.saveField function, you should use the passed-in referral. Instead of
...
ReferralPut.update($scope.referral, function() {
// success
$location.path('/endoadmin');
}, function() {
// error
console.log(error);
});
...
Looking at your code, it looks like this needs to be:
ReferralPut.update(index, function() {
// success
$location.path('/endoadmin');
}, function() {
// error
console.log(error);
});
The $scope.saveField function is passed the current referral in the index field. $scope.referral is undefined in the saveField function.
There may be other issues, but this was the one that stood out the most.

Resources