Restangular does not PUT full object - javascript

I'm very new to it all so if I've made some massive oversights don't shout to hard.
I'm trying to update a table row using restangular. However it would seem like not all the object data is being set to the restapi. I have tested the restapi with POSTMAN so I know that works and I have also created new objects.
With google dev tools the PUT completes 200 OK but the Requested Payload only has the ID of the row. Actually if I attempt this on an existing row with data it clears all the data but the ID!
So here is what I have:
The HTML:
<div ng-controller="networksController">
<h1>{{title}}</h1>
<input type="text" ng-model="search" class="search-query" placeholder="Search">
<table class="table table-striped">
<thead>
<th>ID</th>
<th>Title</th>
<th>Reason</th>
<th>Actions</th>
<th>Requester</th>
<th>Verified</th>
<th></th>
</thead>
<tbody>
<tr ng-repeat="change in changes | filter:search">
<td>{{ change._id }}</td>
<td>
<div class="animate-show" ng-hide="editorEnabled">{{ change.title }}</div>
<div class="animate-show" ng-show="editorEnabled">
<input class="animate-input" type="text" ng-model="change.title" />
</div>
</td>
<td>
<div class="animate-show" ng-hide="editorEnabled">{{ change.reason }}</div>
<div class="animate-show" ng-show="editorEnabled">
<input class="animate-input" type="text" ng-model="change.reason" />
</div>
</td>
<td>
<div class="animate-show" ng-hide="editorEnabled">{{ change.actions }}</div>
<div class="animate-show" ng-show="editorEnabled">
<input class="animate-input " type="text" ng-model="change.actions" />
</div>
</td>
<td>
<div class="animate-show" ng-hide="editorEnabled">{{ change.requester }}</div>
<div class="animate-show" ng-show="editorEnabled">
<input class="animate-input" type="text" ng-model="change.requester" />
</div>
</td>
<td>
<div class="animate-show" ng-hide="editorEnabled">{{ change.verified }}</div>
<div class="animate-show" ng-show="editorEnabled">
<input class="animate-input" type="text" ng-model="change.verified" />
</div>
</td>
<td>
<input type="button" value="Edit" ng-hide="editorEnabled" ng-click="editorEnabled=!editorEnabled" />
<input type="button" value="Save" ng-show="editorEnabled" ng-click="editorEnabled=!editorEnabled; save(change)" />
<button ng-click="destroy(change)">Delete</button>
</td>
</tr>
</tbody>
</table>
The Main Controller:
var app = angular.module('richApp', ['ngResource', 'ngAnimate', 'restangular', 'xeditable'])
.config(function(RestangularProvider) {
RestangularProvider.setBaseUrl('api/');
});
The Page Controller:
app.controller('networksController', ['$scope', '$resource', 'Restangular', function($scope, $resource, Restangular) {
$scope.title = 'Network Control APP';
var baseChanges = Restangular.all('changes');
baseChanges.getList().then(function(changes) {
$scope.allChanges = changes;
});
$scope.changes = Restangular.all('changes').getList().$object;
$scope.destroy = function(change) {
Restangular.one("changes", change._id).remove();
};
$scope.save = function(change) {
Restangular.one("changes", change._id).put();
};
}]);

Ok so after 3 days of hunting high and low I finally find the answer. Mongo and restangular use different ID Keys. mongo uses _id whereas restangular uses id.
In order to correct this I needed to add the following
var app = angular.module('richApp', ['ngResource', 'ngAnimate', 'restangular', 'xeditable'])
.config(function(RestangularProvider) {
RestangularProvider.setBaseUrl('api/');
RestangularProvider.setRestangularFields({ //Added this
id: "_id" //Added this
}); //Added this
});
It's fair to say I also modified the following:
$scope.save = function(change) {
Restangular.one("changes", change._id).get().then(function(data) {
$scope.data = data;
});
var original = change;
$scope.data = Restangular.copy(original);
$scope.data.save();
};

I think you should use
$scope.save = function(change) {
change.put();
};

Related

Angular JS filter Search

I want to retain the selected check boxes as is even when I am
changing my search query. Initially I am posting some query in search
and selecting one of the resulted values, Now if I change my search
query, then New values will be my result. But I want to retain the
checkbox selected for the previous values...
`
//Demo of Searching and Sorting Table with AngularJS
var myApp = angular.module('myApp',[]);
myApp.controller('TableCtrl', ['$scope', function($scope) {
$scope.allItems = getDummyData();
$scope.resetAll = function()
{
$scope.filteredList = $scope.allItems ;
$scope.newEmpId = '';
$scope.newName = '';
$scope.newEmail = '';
$scope.searchText = '';
}
$scope.add = function()
{
$scope.allItems.push({EmpId : $scope.newEmpId, name : $scope.newName, Email:$scope.newEmail});
$scope.resetAll();
}
$scope.search = function()
{
$scope.filteredList = _.filter($scope.allItems,
function(item){
return searchUtil(item,$scope.searchText);
});
if($scope.searchText == '')
{
$scope.filteredList = $scope.allItems ;
}
}
$scope.resetAll();
}]);
/* Search Text in all 3 fields */
function searchUtil(item,toSearch)
{
/* Search Text in all 3 fields */
return ( item.name.toLowerCase().indexOf(toSearch.toLowerCase()) > -1 || item.Email.toLowerCase().indexOf(toSearch.toLowerCase()) > -1 || item.EmpId == toSearch
)
? true : false ;
}
/*Get Dummy Data for Example*/
function getDummyData()
{
return [
{EmpId:2, name:'Jitendra', Email: 'jz#gmail.com'},
{EmpId:1, name:'Minal', Email: 'amz#gmail.com'},
{EmpId:3, name:'Rudra', Email: 'ruz#gmail.com'}
];
}
.icon-search{margin-left:-25px;}
<br /> <br />
<div ng-app="myApp">
<div ng-controller="TableCtrl">
<div class="input-group">
<input class="form-control" ng-model="searchText" placeholder="Search" type="search" ng-change="search()" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-search"></span>
</span>
</div>
<table class="table table-hover data-table sort display">
<thead>
<tr>
<th class="EmpId"> <a href="" ng-click="columnToOrder='EmpId';reverse=!reverse">EmpId
</a></th>
<th class="name"> Name </th>
<th class="Email"> Email </th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in filteredList | orderBy:columnToOrder:reverse">
<td><input type="checkbox" name="test" />{{item.EmpId}}</td>
<td>{{item.name}}</td>
<td>{{item.Email}}</td>
</tr>
</tbody>
</table>
<div class="row">
<div class="col-xs-3">
<input type="text" ng-model="newEmpId" class="form-control" placeholder="EmpId">
</div>
<div class="col-xs-3">
<input type="text" ng-model="newName" class="form-control" placeholder="Name">
</div>
<div class="col-xs-4">
<input type="email" ng-model="newEmail" class="form-control" placeholder="Email">
</div>
<div class="col-xs-1">
<button ng-click="add()" type="button" class="btn btn-primary">
<span class="glyphicon glyphicon-plus"></span>
</button>
</div>
</div>
</div> <!-- Ends Controller -->
</div>
`Fiddle
Try to add ng-model="item.selected" to your checkbox tag
<td><input ng-model="item.selected" type="checkbox" name="test" />{{item.EmpId}}</td>
Works for me, hope it helps.
Looks like this is happening because you are resetting the items here:
if($scope.searchText == '')
{
$scope.filteredList = $scope.allItems ;
}
and allItems doesn't tell anywhere if the checkbox needs to be selected on not. I would suggest you to update the code where you are creating the checkboxes, something like:
<td><input type="checkbox" name="test" ng-model=item.selected ng-checked=item.selected/>
Note that I have updated the item to have a 'selected' field which will tell if that item is selected or not(default could be false). While creating the checkbox I have linked the model using ng-model=item.selected
Updated fiddle at http://jsfiddle.net/3a3zD/194/

why Ng Repeat is not working if button invoked from a different form?

I have a html table that contains an ng repeat directive and two button.The first one will open a modal that contains a new form and let me create my user and then when i click save it will add it to the list.The second one is in the same original form and do the add a user.
What i did not understand why when i click on the first button which is in a different form i can not update the ng repeat however for the second one it's possible.
This is the code:
homepage.jsp
<body ng-app="myApp">
<div class="generic-container" ng-controller="UserController as ctrl">
<div id="createUserContent.jsp" ng-include="createUserContent"></div>
<table>
<tr>
<td>
<button type="button" class="btn btn-primary"
ng-click="ctrl.openCreateUser()">Create</button>
</td>
</tr>
</table>
<table class="table table-hover">
<thead>
<tr>
<th>ID.</th>
<th>Name</th>
<th>Address</th>
<th>Email</th>
<th width="20%"></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="u in ctrl.users">
<td><span ng-bind="u.ssoId"></span></td>
<td><span ng-bind="u.firstName"></span></td>
<td><span ng-bind="u.lastName"></span></td>
<td><span ng-bind="u.email"></span></td>
</tr>
</tbody>
</table>
</div>
</body>
user_controller.js
'use strict';
App.controller('UserController', function ($scope, UserService, $window, $log, $uibModalStack,
$uibModal, $rootScope) {
var self = this;
self.users = [];
self.fetchAllUsers = function () {
console.log('----------Start Printing users----------');
for (var i = 0; i < self.users.length; i++) {
console.log('FirstName ' + self.users[i].firstName);
}
};
/**
this function will not work
**/
self.saveUser = function (user) {
self.users.push(user);
self.fetchAllUsers();
$log.log("saving user");
$uibModalStack.dismissAll();
};
/**
this function works fine
**/
self.addNewRow = function () {
var specialUser = {
id : 12,
firstName : 'john',
lastName: 'travolta',
homeAddress : {location:'chicago'},
email : 'trav#email.com'
};
self.users.push(specialUser);
$log.log("saving specialUser");
};
self.openCreateUser = function () {
var modalInstance = $uibModal.open({
animation : true,
templateUrl : 'createUserContent',
controller : 'UserController',
resolve : {
items : function () {
return $scope.items;
}
}
});
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
self.fetchAllUsers();
});
createUserContent.jsp
<form role="form" ng-controller="UserController as ctrl" >
<div class="form-group">
<label for="FirstName">FirstName</label> <input type="FirstName"
ng-model="ctrl.user.firstName" class="form-control"
id="FirstName" placeholder="Enter FirstName" /> <label
for="lastName">lastName</label> <input type="lastName"
class="form-control" id="lastName"
ng-model="ctrl.user.lastName" placeholder="Enter lastName" />
<label for="email">Email address</label> <input type="email"
ng-model="ctrl.user.email" class="form-control" id="email"
placeholder="Enter email" />
</div>
<div class="form-group">
<label for="homeAddressLocation">Home Address</label> <input class="form-control"
ng-model="ctrl.user.homeAddress.location" id="homeAddressLocation"
placeholder="homeAddressLocation" />
</div>
<div class="form-group">
<label for="SSOId">SSOId</label> <input class="form-control"
ng-model="ctrl.user.ssoId" id="SSOId" placeholder="SSOId" />
</div>
<button type="submit" class="btn btn-default"
ng-click="ctrl.saveUser(ctrl.user)">Save</button>
<button type="submit" class="btn btn-default">Cancel</button>
</form>
Because of your modal template can't access your UserController object and doesn't show error because you used in modal template same controller so reloaded as new Ctrl doesn't refer parent Ctrl.
However better to use different controller and pass parent controller object to modal controller and then modal body can use all parent object. so you should pass parent object to modal controller.
When you include createUserContent.jsp popup file in your main file then no need to use ng-controller="UserController as ctrl" in your modal template you used in modalInstance controller : 'Ctrl',
like:
var modalInstance = $uibModal.open({
templateUrl: 'createUserContent.jsp',
controller: 'ModalCtrl', // ModalCtrl for modal
controllerAs:'modal', // as modal so no need to use in modal template
size: 'lg',
resolve: {
items: function () {
return $scope.items;
},
parent: function(){ // pass self object as a parent to 'ModalCtrl'
return self;
}
}
and ModalCtrl like:
.controller('ModalCtrl', ['parent', function (parent) {
this.parent = parent;
}]);
here used ModalCtrl for modal as modal so you can access parent object like: modal.parent.user
template like:
<form role="form" >
<div class="form-group">
<label for="FirstName">FirstName</label> <input type="FirstName"
ng-model="modal.parent.user.firstName" class="form-control"
id="FirstName" placeholder="Enter FirstName" />
.....
....
<button type="submit" class="btn btn-default"
ng-click="modal.parent.saveUser(modal.parent.user)">Save</button>
<button type="submit" class="btn btn-default">Cancel</button>
</form>
More details Visit PLUNKER DEMO

Angular error : Expected array but received: 0

I'm getting this error when I open up a model partial:
<form action="" novalidate name="newGroupForm">
<div class="modal-body">
<div class="row">
<!-- SELECT THE NUMBER OF GROUPS YOU WANT TO CREATE -->
<label>Select number of groups</label>
<a class="btn" ng-click="newGroupCount = newGroupCount + 1" ng-disabled="newGroupCount == 10" ><i class="fa fa-plus-circle"></i></a>
<input class="groupCounter input-sm" ng-model="newGroupCount" type="number" min="1" max="10" disabled>
<a class="btn" ng-click="newGroupCount = newGroupCount - 1" ng-disabled="newGroupCount == 1"><i class="fa fa-minus-circle"></i></a>
</div>
<br>
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>Group Name</th>
<th>Group Description (optional)</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="i in getNumber(newGroupCount) track by $index">
<td>{{$index+1}}</td>
<td>
<input class= input-sm type="text" required="true" autofocus="true" placeholder="Group name" ng-model="groupData.title[$index]">
</td>
<td>
<input class="form-control input-sm" type="textarea" ng-model="groupData.desc[$index]" placeholder="Group Description">
</td>
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
<button class="btn btn-primary" type="submit" ng-click="submit()" ng-disabled="newGroupForm.$invalid">Create</button>
</div>
</form>
The modal controller looks like this:
spApp.controller('newGroupCtrl',
function newGroupCtrl($scope, $uibModalInstance, GroupService){
$scope.groupData = {
title: [],
desc: []
}
$scope.newGroupCount = 1;
$scope.getNumber = function(num) {
//console.log(num);
return new Array(num);
}
$scope.submit = function(){
$uibModalInstance.close($scope.groupData);
}
$scope.cancel = function (){
$uibModalInstance.dismiss('Cancelled group creation');
};
}
);
Every question I've seen refers to the use of filterbut I'm not using filter. The error repeats whenever I hit the increment button:
<a class="btn" ng-click="newGroupCount = newGroupCount + 1" ng-disabled="newGroupCount == 10" ><i class="fa fa-plus-circle"></i></a>
$scope.getNumber calls new Array(num), which will return an array of undefined values directly proportional to the value of newGroupCount.
For example:
new Array(5) // => [undefined, undefined, undefined, undefined, undefined]
Browsers don't handle that well, since it appears to be an empty array.
You're using ng-repeat in a way that it wasn't quite meant to be used. If I were you, I'd refactor to look something like this:
$scope.groups = [];
$scope.addGroup = function() {
// implement this, and use it in your button that increments the groups
$scope.groups.push(/* whatever */);
}
$scope.removeGroup = function() {
// implement this to remove a group
$scope.groups.splice(/* whatever */);
}
Then in your HTML:
<tr ng-repeat="group in groups">
<!-- display group info -->
</tr>
It may make your life easier here to work with angular (use it how it was intended) instead of fighting against how ng-repeat is meant to work.
The data is generally meant to be in the form of a collection (i.e. [{},{},{}]). Formatting it as such will make it easier for you. See the docs for ng-repeat.

update value not working

I'm trying to perform update on a value but ,the new value that am assigning to it bound to scope value but does not change ,when I edit ,it save with the original empty value
breakdown
$scope.showDepositUpdate = function(birthday) {
$scope.depositValue="one";
$scope.birthday = birthday;
$scope.action = 'deposit';
$scope.isAdd = false;
$scope.showUpdateModal = true;
};
$scope.updateDeposit = function() {
$scope.birthday.Name = $scope.depositValue;
StoreFactory.updateBirthday($scope.birthday);
$scope.depositValue='';
newValue =""
$scope.showUpdateModal = false;
};
but scope.depositValue does not update it according to value on the view , it always concat to "", here is my view
<form class="form-inline" ng-show="showUpdateModal">
<h2 class="title">{{ action }} Birthday</h2>
<div class="form-group">
<input type="text" class="form-control" ng-model="birthday.Name" placeholder="name" placeholder="Jane Doe">
</div>
<div class="form-group">
<input type="text" class="form-control" ng-model="depositvalue" placeholder="name" placeholder="deposit">
</div>
<button ng-click="updateDeposit()" class="btn btn-default btn-lg btn-rounded">Save</button>
</form>
<tr ng-repeat="birthday in birthdays">
<td>{{ birthday.Name }}</td>
<td>{{ birthday.Date }}</td>
<td> <button class="btn btn-info btn-sm btn-rounded" ng-click="showDepositUpdate(birthday)">deposit</button>
In your function $scope.updateDeposit you are stting up the value of the variable depositValue to "". $scope.depositValue='';. Maybe this is your problem?
I've done a snipet to show you that.
See if it is what you want.
var $scope = {};
var myApp = angular.module('myApp', []);
var StoreFactory = {
updateBirthday: function(){return true} // JUST A MOCKUP
};
myApp.controller('myCtrl', ['$scope',
function($scope) {
$scope.showDepositUpdate = function(birthday) {
$scope.depositValue = "one";
$scope.birthday = birthday;
$scope.action = 'deposit';
$scope.isAdd = false;
$scope.showUpdateModal = true;
};
$scope.updateDeposit = function() {
$scope.birthday.Name = $scope.depositValue;
StoreFactory.updateBirthday($scope.birthday);
$scope.depositValue = '';
newValue = ""
$scope.showUpdateModal = false;
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<form class="form-inline" ng-show="showUpdateModal">
<h2 class="title">{{ action }} Birthday</h2>
<div class="form-group">
<input type="text" class="form-control" ng-model="birthday.Name" placeholder="Jane Doe">
</div>
<div class="form-group">
<input type="text" class="form-control" ng-model="depositvalue" placeholder="deposit">
</div>
<button ng-click="updateDeposit()" class="btn btn-default btn-lg btn-rounded">Save</button>
</form>
<tr ng-repeat="birthday in birthdays">
<td>{{ birthday.Name }}</td>
<td>{{ depositvalue }}</td>
<td>
<button class="btn btn-info btn-sm btn-rounded" ng-click="showDepositUpdate(birthday)">deposit</button>
</td>
</tr>
Did you try a console.log() of the value in your Factory? Whats the value there?
I once had such a problem and that was because (referred to your problem)
$scope.birthday.Name
is just a reference to $scope.depositValue and so you pass a reference to a function that is changed quite after function call ($scope.depositValue = '').
Would be good to know what StoreFactory.updateBirthday($scope.birthday); actually does.

angularjs $valid not working on fields

I am new to angularjs.
I have 2 buttons on my form and one is Save and other is Test Connection button.
<td align="left" colspan="0" >
<input class="form-control" title="Specifies the IP address of the SIP trunk ethernet connection." placeholder="xxx.xxx.xxx.xxx"
style="display: inline-block;display:block;white-space: nowrap;overflow: hidden;" type="text"
name="pabxipaddress" id="pabxipaddress" ng-model="userSetup.pabxipaddress" required ng-pattern='patternPresent' >
</td>
<td>
<span class="error" ng-show="(testIPOfficeFlag || submitted) && userSetupForm.pabxipaddress.$error.required">
<label style="color: red;">Required!</label>
</span>
<span class="error" ng-show='(testIPOfficeFlag || submitted) && userSetupForm.pabxipaddress.$error.pattern'>
<label style="color: red;">Invalid IP Address!</label>
</span>
</td>
Now in my JS file when I do like,
$scope.userSetup.pabxipaddress.$valid for some dynamic testing it gives me
TypeError: Cannot read property '$valid' of undefined
when I alert like $scope.userSetup.pabxipaddress it displays the data correctly.
How to check whether individual field is correct and passed all constraints attached to it.
The valid property is not part of the model value... try
$scope.userSetupForm.postdail.$valid
where userSetupForm is the name of the form and postdail is the name of the input element.
var app = angular.module('my-app', [], function() {
})
app.controller('AppController', function($scope) {
$scope.check = function() {
$scope.validity = {
field1: $scope.myform.myfield1.$valid,
field2: $scope.myform.myfield2.$valid,
field3: $scope.myform.myfield3.$valid
}
};
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="my-app" ng-controller="AppController">
<form name="myform" novalidate>
<div>
<input type="number" name="myfield1" ng-model="formdata.myfield1" required class="numbers-only-for" minvalue="1" maxvalue="45">
</div>
<div>
<input type="text" name="myfield2" ng-model="formdata.myfield2" required>
</div>
<div>
<input type="text" name="myfield3" ng-model="formdata.myfield3" required>
</div>
<button ng-click="check()">Check</button>
</form>
<pre>{{formdata | json}}</pre>
<pre>{{validity | json}}</pre>
</div>

Categories

Resources