#ModelAttribute in my REST comes empty - javascript

I am trying to pass data through <select multiple> from HTML to my RESTful.
That data is an array of String. I don't know why when it comes to my backend it's empty.
This is my REST:
#PutMapping("/events")
#Timed
public ResponseEntity<Event> updateEvent(#RequestBody Event event, #ModelAttribute("attendeesToParse") ArrayList<String> attendeesToParse) throws URISyntaxException {
//Some code
}
This is my HTML:
<div class="form-group">
<label>Attendees</label>
<select class="form-control" multiple name="attendeesToParse" ng-model="vm.usernames"
ng-options="customUser as customUser.username for customUser in vm.customusers">
<option value=""></option>
</select>
</div>
I tried to fix this one for days, I googled it so much but I found no solutions. Please help me.
I can not change my HTML into a JSP due to my project's structure and business logic.
Why does it come empty? If I try to show some logs I see an empty array [].
UPDATE
My HTML form call:
<form name="editForm" role="form" novalidate ng-submit="vm.save()">
<!-- some code -->
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal" ng-click="vm.clear()">
<span class="glyphicon glyphicon-ban-circle"></span> <span data-translate="entity.action.cancel">Cancel</span>
</button>
<button type="submit" ng-disabled="editForm.$invalid || vm.isSaving" class="btn btn-primary">
<span class="glyphicon glyphicon-save"></span> <span data-translate="entity.action.save">Save</span>
</button>
</div>
</form>
My event-dialog-controller.js: (is the .js controller that works with form)
(function() {
'use strict';
angular
.module('businessRequestApp')
.controller('EventDialogController', EventDialogController);
EventDialogController.$inject = ['$timeout', '$scope', '$stateParams', '$uibModalInstance', '$q', 'entity', 'Event', 'Desk', 'CustomUser'];
function EventDialogController ($timeout, $scope, $stateParams, $uibModalInstance, $q, entity, Event, Desk, CustomUser) {
var vm = this;
vm.event = entity;
vm.clear = clear;
vm.datePickerOpenStatus = {};
vm.openCalendar = openCalendar;
vm.save = save;
vm.reftables = Desk.query({filter: 'event-is-null'});
$q.all([vm.event.$promise, vm.reftables.$promise]).then(function() {
if (!vm.event.refTable || !vm.event.refTable.id) {
return $q.reject();
}
return Desk.get({id : vm.event.refTable.id}).$promise;
}).then(function(refTable) {
vm.reftables.push(refTable);
});
vm.customusers = CustomUser.query();
$timeout(function (){
angular.element('.form-group:eq(1)>input').focus();
});
function clear () {
$uibModalInstance.dismiss('cancel');
}
function save () {
vm.isSaving = true;
if (vm.event.id !== null) {
Event.update(vm.event, onSaveSuccess, onSaveError);
} else {
Event.save(vm.event, onSaveSuccess, onSaveError);
}
}
function onSaveSuccess (result) {
$scope.$emit('businessRequestApp:eventUpdate', result);
$uibModalInstance.close(result);
vm.isSaving = false;
}
function onSaveError () {
vm.isSaving = false;
}
vm.datePickerOpenStatus.date = false;
function openCalendar (date) {
vm.datePickerOpenStatus[date] = true;
}
}
})();
My event-service.js:
(function() {
'use strict';
angular
.module('businessRequestApp')
.factory('Event', Event);
Event.$inject = ['$resource', 'DateUtils'];
function Event ($resource, DateUtils) {
var resourceUrl = 'api/events/:id';
return $resource(resourceUrl, {}, {
'query': { method: 'GET', isArray: true},
'get': {
method: 'GET',
transformResponse: function (data) {
if (data) {
data = angular.fromJson(data);
data.date = DateUtils.convertLocalDateFromServer(data.date);
}
return data;
}
},
'update': {
method: 'PUT',
transformRequest: function (data) {
var copy = angular.copy(data);
copy.date = DateUtils.convertLocalDateToServer(copy.date);
return angular.toJson(copy);
}
},
'save': {
method: 'POST',
transformRequest: function (data) {
var copy = angular.copy(data);
copy.date = DateUtils.convertLocalDateToServer(copy.date);
return angular.toJson(copy);
}
}
});
}
})();
My event.controller.js:
(function () {
'use strict';
angular
.module('businessRequestApp')
.controller('EventController', EventController);
EventController.$inject = ['Event', 'CustomUser', '$scope'];
function EventController(Event, CustomUser, $scope) {
var vm = this;
vm.events = [];
vm.customUsers = [];
vm.usernames = ["test1", "test2", "test3"];
$scope.allCustomUsers = [];
loadAll();
function loadAll() {
Event.query(function (result) {
vm.events = result;
vm.searchQuery = null;
});
CustomUser.query(function (result) {
vm.customUsers = result;
vm.searchQuery = null;
for (var i = 0; i < vm.customUsers.length; i++) {
$scope.allCustomUsers.push(vm.customUsers[i].username);
}
});
}
}
})();

If you're using angularJS, you can't data bind data with #ModelAttribute, because #ModelAttribute exists only with template engines such as JSP, and AngularJS is not a template engine within Spring. Try instead to use #RequestBody on String parameter, and then extract the data using Jackson.
One more issue, How exactly do you pass your values from front to back? I don't see any $http angularJS call, and no HTML form with POST method.

Related

Trying to activate a checkbox from a controller that lives in another controller

I am trying to activate a checkbox from a controller that lives in another controller. For example, I have a card named information technology under a separate controller and when I click this I want it to route to another page that has a checkbox for information technology from another controller and I want it checked as it renders the page.
The application architecture is very lengthy so I wont include any code base here. But I would like to know an approach I can take.
This is the controller where I want the logic to live and to mark a text box as checked (which lives on another controller).
angular
.controller("mycontroller", mycontroller);
mycontroller.$inject = [
"$scope"
];
// getting the getData() data
$scope.getData = function (data, type) {
console.log("whats this data about in getData(data) ", data)
$scope.query = data.name;
if (data.checked == undefined) {
data.checked = true;
}
}
Below: Is the controller where the checkbox controller lives
angular
.controller('supplierIntelligenceCtrl', function ($scope, $q, FetchData, dataStore, SharedService,
$document, $window, $state, $rootScope, $timeout, DataCache,
$filter, $interval, $localStorage, $http) {
$scope.getData = function (data, type) {
console.log("whats this data about in getData(data) ", data)
$scope.query = data.name;
if (data.checked == undefined) {
data.checked = true;
}
}
$scope.apply = function (type) {
$scope.select = false;
$scope.bigres = 0;
$scope.mobFil = 3;
$scope.applyFilter(type);
}
$scope.disableApply = false;
$scope.disableApply2 = false;
$scope.applyFilter = function (type) {
console.log("this is type ", type)
if (type == 'industries') {
$scope.filters.industries = $scope.industries.filter(function (e) {
console.log("this is e ", e.checked)
return e.checked;
}).map(function (f) {
console.log(" this is f >>>> ",
f)
return f.id
})
$scope.filters.countries = [];
if ($scope.countries != undefined) {
$scope.countries = $scope.countries.map(function (e) {
e.checked = false;
return e;
})
}
$scope.filters.cities = [];
if ($scope.cities != undefined) {
$scope.cities = $scope.cities.map(function (e) {
e.checked = false;
return e;
})
}
$scope.start = 0;
if ($scope.filters.industries.length > 0) {
$scope.callBackend();
$scope.disableApply2 = true;
FetchData.fetchDNBCountriesByIndustries('industries=' + $scope.filters.industries + '&size=').then(function (res) {
$scope.disableApply2 = false;
$scope.countries = res.data;
$scope.countriesPage += 10
}, function () {
$scope.disableApply2 = false;
});
} else {
$scope.callBackend();
}
}
if (type == 'countries') {
$scope.filters.countries = $scope.countries.filter(function (e) {
return e.checked;
}).map(function (f) {
return f.id;
})
$scope.filters.cities = [];
if ($scope.cities != undefined) {
$scope.cities = $scope.cities.map(function (e) {
e.checked = false;
return e;
})
}
$scope.start = 0;
if ($scope.filters.countries.length > 0) {
$scope.callBackend();
$scope.disableApply2 = true;
FetchData.fetchDNBCitiesByIndustriesAndCountries('industries=' + $scope.filters.industries + '&countries=' + $scope.filters.countries + '&size=').then(function (res) {
$scope.disableApply2 = false;
$scope.cities = res.data;
}, function () {
$scope.disableApply2 = false;
})
} else {
$scope.callBackend();
}
}
if (type == 'cities') {
$scope.filters.cities = $scope.cities.filter(function (e) {
return e.checked;
}).map(function (f) {
return f.id
})
$scope.start = 0;
$scope.callBackend();
}
if (type == 'classifications') {
$scope.filters.classifications = $scope.classifications.filter(function (e) {
return e.checked;
}).map(function (f) {
return f.statusCode;
})
$scope.start = 0;
$scope.callBackend();
}
}
}
Here is the HTML where the checkbox lives:
<div ng-repeat="data in industries ">
<input id="{{data.id}}in" type="checkbox" aria-invalid="false"
ng-model="data.checked"
ng-change="getData(data,'industry')">
<label for="{{data.id}}in">{{data.name}}</label>
</div>
Maybe Im missing the point here and perhaps am overlooking something. Im new to angularjs and need to implement this capability to route a button/card to another page that checks a checkbox filter.
Please - any advise would be great . :)
Here is an example of controllers sharing an array via a shared service injected by the dependency injector. Check the checkbox in one controller and it shows in the other.
angular.module('app', []);
angular.module('app')
.factory('dataService', [function () {
return {
data: [
{ prop: '1', checked: false },
{ prop: '2', checked: false },
{ prop: '3', checked: false },
{ prop: '4', checked: false }
]
};
}]);
angular.module('app')
.controller('controller1', ['dataService', function (dataService) {
this.data = dataService.data;
}]);
angular.module('app')
.controller('controller2', ['dataService', function (dataService) {
this.data = dataService.data;
}]);
angular.module('app')
.controller('controller3', ['dataService', function (dataService) {
this.toggleAll = () => {
dataService.data.forEach(item => item.checked = !item.checked)
};
}]);
[ng-controller] { display: inline-block; margin-right: 30px; vertical-align: top; }
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="controller1 as ctrl">
<strong>Controller 1</strong>
<div ng-repeat="item in ctrl.data">
<label>Item {{item.prop}} <input type="checkbox" ng-model="item.checked"></label>
</div>
</div>
<div ng-controller="controller2 as ctrl">
<strong>Controller 2</strong>
<div ng-repeat="item in ctrl.data">
<label>Item {{item.prop}} <input type="checkbox" ng-model="item.checked"></label>
</div>
</div>
<div ng-controller="controller3 as ctrl">
<strong>Controller 3</strong>
<div>
<button ng-click="ctrl.toggleAll()">Toggle all</button>
</div>
</div>
</div>
Put industries as a property on a shared service that you inject into both of the controllers by the dependency injector. Then one controller can bind it to it's view and the other one can change the checked properties on them.
Since you are talking about redirection and then checking a check box, you can try either of below options
Send selection 'information technology' in query string to redirected page and check the check box
If you own a back end server then put the value in cookie and read it in your angular js app
Hope this helps.

angularjs: saving multiple students at the same time

i am trying to save number of students at the time,i wrote the following code but i did not know where to go further. any more info or links to resources regarding this topic would be much appreciated
what i have done so far :
<div ng-controller="MainCtrl">
<fieldset data-ng-repeat="student in students">
<input type="text" ng-model="student.class" name="" placeholder="Class Name ">
<input type="text" ng-model="student.firstname" name="" placeholder="First Name ">
<input type="text" ng-model="student.lastname" name="" placeholder="Last Name ">
<button class="btn btn-danger" ng-show="$last" ng-click="removeStudent()">-</button>
</fieldset>
<button class="btn btn-primary" ng-click="addNewStudent()">New Student</button>
<button class="btn btn-primary" ng-click="save()">Save</button>
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>
the controller is:
app.controller('MainCtrl', function($scope, $modalInstance, $students) {
$scope.students = [];
$scope.addNewStudent = function() {
$scope.students.push({
classname: "",
firstname: "",
lastname: ""
});
};
$scope.removeStudent = function() {
var lastItem = $scope.students.length - 1;
$scope.students.splice(lastItem);
};
$scope.save = function() {
$modalInstance.close($scope.students);
};
$scope.delete = function() {
$scope.students['deleted'] = 1;
$modalInstance.close($scope.students);
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
});
in the view i can write the infos of students but when i click save button it only save the first student
modal instance:
$scope.openStudent = function (student) {
var modalInstance = $modal.open({
templateUrl: 'modalStudent.html',
controller: 'mainCTRL',
windowClass:'app-modal-window',
resolve: {
students: function () {
var students= {};
if (student !== undefined){
students['classname'] = student.classname;
students['firstname'] = student.firstname ;
students['lastname'] = student.lastname;
students['nachname'] = student.nachname;
}
console.log("studinfo",students);
return students;
}
}
});
modalInstance.result.then(function (students) {
if (students.deleted === undefined || students.deleted == 0) {
oStudent = { classname: students.classname,
firstname: students.firstname,
lastname: students.lastname,
delete_time:"0000-00-00 00:00:00"
};
saveStudent( $indexedDB,Student).then( function(id) {
$scope.buildMenu();
});
} else {
oStudent = { id: students.id,
delete_time:new Date().toISOString()
};
deleteStudent( $indexedDB, $scope, students.id).then( function(id) {
saveStudent( $indexedDB, Student, $scope.selectedUser.id ).then( function(id) {
$scope.buildMenu();
});
});
}
}, function () {
//console.log('Modal Student dismissed at: ' + new Date());
});
}
In case its a modal where you are passing the existing students objects, your controller code should be modified as:
Also you should use two separate views in this case for add and edit to avoid code cluttering. Because in case of addition students will be an array of objects and in case of edit it will be a single object where you cannot use ng-repeat as it wont work
app.controller('MainCtrl', function($scope, $modalInstance, students) {
//students variable contains information about the student to be edited, so your code should be something like this
if(students.classname !== undefined){
$scope.students = students;
}else{
$scope.students = [];
}
// rather than re-initializing each time modal gets opened you should retain value from students that you are passing
$scope.addNewStudent = function() {
$scope.students.push({
classname: "",
firstname: "",
lastname: ""
});
};
$scope.removeStudent = function() {
var lastItem = $scope.students.length - 1;
$scope.students.splice(lastItem);
};
$scope.save = function() {
$modalInstance.close($scope.students);
//make sure to save this when modal closes in the variable you are returning students from when modal is triggered
};
$scope.delete = function() {
$scope.info['deleted'] = 1;
$modalInstance.close($scope.students);
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
});

Why am I getting "Incorrect injection token!" in this angular application code?

I'm trying to setup a restful API interface via AngularJS with the following code:
'use strict';
(function(angular) {
function ApiAction($resource, ResourceParameters) {
return $resource(ResourceParameters.route,
{ },
{ api_index: {
method: ResourceParameters.method,
isArray: true
}
});
return $resource(ResourceParameters.route,
{ },
{ create: {
method: ResourceParameters.method,
isArray: true
}
}
);
}
function ResourceParameters($scope) {
var factory = {};
factory.method = '';
factory.route = '';
factory.SetMethod = function(method) {
factory.method = method;
}
factory.SetRoute = function(route) {
factory.route = route;
}
return factory;
}
function superheroCtr($scope, ApiAction, ResourceParameters) {
$scope.superheroSubmit = function() {
// ApiAction.create({}, { superhero_name: $scope.superheroName, age: $scope.superheroAge });
angular.forEach($scope.superheroes, function(hero) {
// ApiAction.create({}, { superhero_name: hero.superhero_name, age: hero.age });
});
};
var heroesResources = ResourceParameters($scope).SetRoute('/api/');
var heroes = ApiAction.api_index({}, heroesResources);
$scope.superheroes = [];
heroes.$promise.then(function(data) {
angular.forEach(data, function(item) {
$scope.superheroes.push(item);
});
}, function(data) {
//if error then...
});
$scope.appendSuperheroFields = function() {
var i = $scope.superheroes.length + 1;
$scope.superheroes.push({"id": i, age: "", superhero_name: "" })
}
}
var superheroApp = angular.module('superheroApp', ['ngResource']);
superheroApp.controller('superheroCtr', ['$scope', 'ApiAction', 'ResourceParameters', superheroCtr]);
superheroApp.factory('ResourceParameters', ['$scope', ResourceParameters]);
superheroApp.factory('ApiAction', ['$resource', ResourceParameters, ApiAction]);
})(angular);
Yet, when I run it I get the following error:
Error: [$injector:itkn] Incorrect injection token! Expected service name as string, got function ResourceParameters($scope)
Why is this?
Simply you can not inject $scope OR you can not have access to $scope
inside a factory
Your problem is at this line
superheroApp.factory('ResourceParameters', ['$scope', ResourceParameters]);
You need to replace that line with
superheroApp.factory('ResourceParameters', [ResourceParameters]);
Factory
function ResourceParameters() { //<--removed $scope from here
var factory = {};
factory.method = '';
factory.route = '';
factory.SetMethod = function(method) {
factory.method = method;
}
factory.SetRoute = function(route) {
factory.route = route;
}
return factory;
}
Update
Additionally you should correct the declaration of ApiAction where ResourceParameters should be placed inside ' single qoutes
superheroApp.factory('ApiAction', ['$resource', 'ResourceParameters', ApiAction]);

Showing authorised content with Angularjs

app.controller('PageCtrl', ['$scope', '$stateParams', '$state', 'USER_ROLES', 'AuthService', function($scope,$stateParams,$state,USER_ROLES, AuthService){
//console.log("Page Controller reporting for duty.");
$scope.currentUser = null;
$scope.currentUserExists = false; //<- defined in scope of PageCtrl
$scope.userRoles = USER_ROLES;
$scope.isAuthorized = AuthService.isAuthorized;
$scope.setCurrentUser = function (user) {
$scope.currentUser = user;
$scope.currentUserExists = true; //<- set true here!!
};
Now in my html code I'm doing:
<body ng-app="myApp" ng-controller="PageCtrl">
....
<div class="navbar-brand" ng-if="currentUserExists">Welcome!!</div>
<div class="navbar-brand" ng-if="currentUser.data.teacher._id">Welcome2!!</div>
Iv tried ng-show, and I'm trying both examples above to test it.
If i log to console currentUser within my js file everything appears to be working normal. But nothing will show on my page.
Am i missing something??
currentUser is json set like:
$scope.login = function (credentials) {
AuthService.login(credentials).then(function (user) {
$rootScope.$broadcast(AUTH_EVENTS.loginSuccess);
$scope.setCurrentUser(user);
console.log("currentuser");
console.log($scope.currentUser.data.teacher._id); //Yes its working...
}, function () {
$rootScope.$broadcast(AUTH_EVENTS.loginFailed);
});
};
...
authService.login = function (credentials) {
return $http({
method: 'POST',
url: 'proxy2.php',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
transformRequest: function(obj) {
var str = [];
for(var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
data: {
url: 'http://teach.classdojo.com/api/dojoSession?_u=tid',
login: credentials.login,
password: credentials.password,
type: 'teacher'
}
}).success(function (res) {
alert("login success");
Session.create(res.teacher._id, "admin");
return res.teacher;
}).error(function (res) {
alert(res.error.detail);
});
};
You may want to try this:
<div class="navbar-brand" ng-if="currentUserExists==true">Welcome!!</div>
The problem may be due to your setting a primitive value on the scope.
Try using view.currentUserExists instead- so set $scope.view = {currentUserExists: false} in the initialization and then $scope.view.currentUserExists = true in the promise resolution.
I couldn't understand why the scope wasn't working on the page, apparently due to inheritence or maybe because i was using $scope in two controllers?
Anyway i solved it using a service:
$scope.login = function (credentials) {
AuthService.login(credentials).then(function (user) {
userService.setCurrentUser(user); //<----Added this
$rootScope.$broadcast(AUTH_EVENTS.loginSuccess);
}, function () {
$rootScope.$broadcast(AUTH_EVENTS.loginFailed);
});
};
...
var updateUser = function() {
scope.view.currentUser = userService.getCurrentUser();
};
scope.$on(AUTH_EVENTS.loginSuccess, updateUser);
..
app.service('userService', function() {
var currentUser = null;
return {
setCurrentUser: function(user) {
currentUser = user;
},
getCurrentUser: function() {
return currentUser;
}
};
});

AngularsJS list and edit with 2 controllers

I try to do my first angularjs application, but i have a problem. I have 2 controllers (and i would like to keep 2): the first to list items, the second to edit or create an item.
When I save an item, or create a new item, i can't edit another or create another, after to do one action the form can't load or save... The problem seems to be this line :
$scope.editPlace = {};
But I don't understand why...
DEMO :
http://jsfiddle.net/cxL7qmke/
HTML:
<div ng-app="mapApp">
<div ng-controller="EditPlaceCtrl">
<form name="editPlaceForm">
<fieldset>
<label for="title">Title:</label>
<input id="title" type="text" ng-model="editPlace.title">
<input type="hidden" ng-model="editPlace.id" />
<button type="submit" ng-click="savePlace()">Save</button>
</fieldset>
</form>
</div>
<section ng-controller="PlaceCtrl">
<ul>
<li ng-repeat="place in places">
<label>{{place.title}} edit</label>
</li>
</ul>
</section>
</div>
JS :
var mapApp = angular.module('mapApp', []);
mapApp.controller('PlaceCtrl', function ($scope, $rootScope, placeService) {
$scope.places = placeService.getAll();
$scope.edit = function (id) {
$rootScope.editPlace = angular.copy(placeService.get(id));
}
});
mapApp.controller('EditPlaceCtrl', function ($scope, placeService) {
$scope.savePlace = function () {
placeService.save($scope.editPlace);
$scope.editPlace = {};
}
});
mapApp.service('placeService', function ($filter) {
var uid = 3;
var places = [
{ id: 1, title: 'Item1', lat: 43.123, lng: -89.123 },
{ id: 2, title: 'Item2', lat: 43.321, lng: -89.321 }
];
this.getAll = function () {
return places;
}
this.get = function (id) {
var place, i;
for (i in places) {
if (places[i].id === id) {
return places[i];
}
}
return false;
};
this.save = function (place) {
if (place.id == null) {
place.id = this.uid++;
places.push(place);
} else {
for (i in places) {
if (places[i].id == place.id) {
places[i] = place;
}
}
}
};
});
I've made few changes and seems to work for me please see here
http://jsfiddle.net/m9bevovy/
in your service I've added
this.newPlace = {};
this.setNew = function (id) {
this.newPlace = this.get(id);
};
and your controllers :
mapApp.controller('PlaceCtrl', function ($scope, $rootScope, placeService) {
$scope.places = placeService.getAll();
$scope.edit = function (id) {
placeService.setNew(id);
}
});
mapApp.controller('EditPlaceCtrl', function ($scope, placeService) {
$scope.placeService = placeService;
$scope.savePlace = function () {
placeService.save($scope.placeService.newPlace);
$scope.placeService.newPlace = {};
}
});
You are using both $scope and $rootScope to hold the reference to editPlace.
If you want to use the $rootScope, use this in your savePlace function:
$rootScope.editPlace = {};
Instead of:
$scope.editPlace = {};
Here`s the working fiddle

Categories

Resources