Submitting form by AngularJs in spring mvc - javascript

I am new to Angularjs and trying to save table by using angularjs in spring mvc.
My table and controller is :
#Entity
public class StudentSkills {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
private int skillId;
private String skillName;
private int expMonth;
private int expYear;
private String experties;
#ManyToOne
#JoinColumn(name= "student")
#JsonIgnore
private Student student;
// Getters Setters
My jsp page is : The Angularjs Coding is probably not correct
<script>
var skillApp = angular.module('skillApp', []);
skillApp.controller('skills', function($scope, $http) {
$scope.refreshSkill = function(){
$http.get('/user/getuserskills')
.success(function(data) {
$scope.allSkills = data;
});
};
$scope.addSkill = function(skill){
$http.put('/user/addskill/'+skill)
.success($scope.refreshSkill());
};
});
</script>
<title>Add Skill</title>
</head>
<body>
<div ng-app="skillApp">
<div ng-controller="skills" ng-init="refreshSkill()">
<div ng-repeat="skill in allSkills">
<div class="col-sm-6 col-lg-3">
<div class="thumbnail">
<div class="caption">
<h5>Name : {{skill.skillName}}</h5>
<h5>Name : {{skill.expMonth}}</h5>
<h5>Name : {{skill.expYear}}</h5>
<h5>Name : {{skill.experties}}</h5>
</div>
</div>
</div>
</div>
<form novalidate ng-submit="addSkill(skill)">
<input type="text" ng-model="skill.skillName">
<input type="text" ng-model="skill.expMonth">
<input type="text" ng-model="skill.expYear">
<input type="text" ng-model="skill.experties">
<input type="button" id="submit" value="Submit">
</form>
</div>
</div>
</body>
My Controller is :
#RequestMapping(value= "getuserskills", method = RequestMethod.GET)
public #ResponseBody List<StudentSkills> getStudentSkills(Model model){
List<StudentSkills> skills = studentService.getAllSkills(getStudentName());
return skills;
}
#RequestMapping(value = "/addskill", method = RequestMethod.PUT)
#ResponseStatus(value = HttpStatus.NO_CONTENT)
public void update(#PathVariable("skill") StudentSkills skills) {
skills.setStudent(studentService.getStudent(getStudentName()));
studentService.addStudentSkill(skills);
}
I want to fetch all the skills saved by using refreshSkill() function, and submit new skills through form. It is not working and i have tried but could not get it to work. How to link form like we can link using #modelAttribute. Or any other way to submit form using ajax. Thank You.

maybe you should follow some Angular JS tutorial or example, such as Angular phone tutorial, and this guide of the notion scope.
There are several problems in your codes :
1, you should define the json object skill in your controller, so that your view can recognize it : $scope.skill={};.
2, as the api of $http.put shows, the syntax should be : put(url, data, [config]);. So you should modify your code to
$http.put('/user/addskill/', $scope.skill).success($scope.refreshSkill());
3, in the server side, you should use the annotation #RequestBody for the StudentSkills parameter, like this :
public void update(#RequestBody StudentSkills skills) {
// your codes ...
}
Because the annotation #PathVariable is for the uri parameter, and when you use http put, the parameter is stored in the request body.
Hope help!

Related

Using C# MVC multiple dynamic models in View

I have a View with several form that I'm using for searching and displaying the results as partial View in like SearchByNumber, SearchByVehicle, etc.
I'm trying to load view and execute search for different forms by posting link with querystring like www.example.com/Search?number=101010 from different view.
For the first form, SearchByNumber I only have one parameter, string number and i'm returning view with dynamic Model and its working like it should, but I only manage to make search for this form.
Here is my controller:
public ActionResult Index(string number)
{
return View(model: number);
}
and in the View I have:
<form id="searchbynumberform">
Search By Any Number:
<div class="input-group input-group-sm">
<input type="text" class="form-control" name="number" id="number" value="#Model">
<span class="input-group-btn">
<button class="btn btn-primary" type="button" name="numbersearch" id="numbersearch" disabled>
Search
</button>
</span>
</div>
</form>
My Question is, if anyone can help me, How to perform search let's say on the second form where I have int type and string name parameters?
Thank You in advance...
At the moment your Model is only the search string that was entered, which seems rather incomplete. It would make a lot more sense if the Model also contained the actual search results, which after all is what the user wants to see. And then you can also add the other search properties.
The MVC approach for this is to create a (View)Model class, somewhere in your project, something like this:
public class SearchModel
{
public string Number { get; set; }
public int? Type { get; set; }
public string Name { get; set; }
public List<SearchResult> SearchResults { get; set; }
}
And then use it e.g. like this:
public ActionResult Index(string number)
{
var model = new SearchModel
{
Number = number,
SearchResults = GetByNumber(number)
};
return View(model);
}
public ActionResult IndexOther(int type, int name)
{
var model = new SearchModel
{
Type = type,
Name = name,
SearchResults = GetByTypeAndName(type, name)
};
return View(model);
}
And in your Index.cshtml:
#model SearchModel
#* You can now use Model.Number, Model.Type, Model.Name and Model.SearchResults. *#

Set path of selected file to model in view

I am trying to set the full path of the selected file into the model in the view.
Controller FileController:
public async Task<IActionResult> Create(CreateFileViewModel model)
{
if (ModelState.IsValid)
{
var file = new File
{
Path = model.Path
};
_context.Add(file);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(model);
}
Model CreateFileViewModel:
public class CreateFileViewModel
{
public string Path { get; set; }
}
Model File:
public class File
{
public int Id { get; set; }
public string Path { get; set; }
}
ViewForm Create:
<form asp-action="Create">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Path" class="control-label"></label>
<input asp-for="Path" id="selectedFile" type="file" />
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
Script in Create:
<script>
document.getElementById('selectedFile').onmouseout = function () {
#Model.Path=this.value;
};
</script>
But
#Model.Path=this.value;
this not working. Ofc I cannot convert between razor and javascript variables. But I don't know another way how to set full path of selected file into the model variable.
This
<input asp-for="Path" id="selectedFile" type="file" />
set into model variable just file name, without a path.
#Model.Path is server side i.e. c# code, while this.value is java script code which is client side code, so the server side code will get executed when view is rendered while your js code with execute on particular event in your html.
What you need is to update the hidden value via javascript and it will post back in controller with updated value and will also work in html with the updated value.
Your hidden field will be rendered with id Path, so you can write :
document.GetElementById("Model").value = this.value;
or if you have jquery library included in your application, then you can make use of that as well:
$("#Path").val(this.value);
This way when the model will get posted back to controller, the Path property will have the updated value which would be the path you have assigned via js code.
Hope it helps!

how to load json data returned via ajax call in custom modal dialog

I'm newbie and wanna favor that is I have a link to open a custom modal dialog( not a bootstrap modal) as following
<div class="uk-modal" id="edit_quiz">
<div class="uk-modal-dialog">
<form:form method="post" commandName="quiz" htmlEscape="false" cssClass="uk-form-stacked">
<div class="uk-margin-medium-bottom">
<label for="task_title">Quiz Title</label>
<form:hidden path="quizId"/>
<form:input type="text" cssClass="md-input" id="quiz_title" path="quizTitle"/>
</div>
<div class="uk-margin-medium-bottom">
<label for="task_description">Description</label>
<form:textarea cssClass="md-input" id="quiz_description" path="quizDescription"/>
</div>
<div class="uk-modal-footer uk-text-right">
<button type="button" class="md-btn md-btn-flat uk-modal-close">Close</button>
<input type="submit" class="md-btn md-btn-flat md-btn-flat-primary" id="quiz_new_save" value="Update Quiz"/>
</div>
</form:form>
</div>
</div>
and at last my ajax script is
<script type="text/javascript">
$('#edit_quiz').click(function (event){
event.preventDefault();
$.ajax({
type : "GET",
url : "${pageContext.request.contextPath}/quiz/1",
data : {
"quizTitle" : "${quizTitle}"
},
success: function(data){
$('#edit_quiz_title').val(data.quizTitle);
}
})
return false; //for good measure
});</script>
this opens up the dialog but there are some issues those are:
the data is loaded using the
url : "${pageContext.request.contextPath}/quiz/1", I want to be this dynamic means Is there any way to get the id of selected quiz from a list of quizzes and get the data accordingly in modal form?
the data is shown in the form input field when it is focused how can data be filled without focus?
My RestController
#RestController
public class AdminRestController {
#Autowired
private QuizService quizService;
#RequestMapping(value = "/quiz_list/", method = RequestMethod.GET, headers="Accept=*/*", produces="application/json")
public ResponseEntity<Set<Quiz>> quizList() {
Set<Quiz> quizs = quizService.findAllQuizzes();
if(quizs.isEmpty()){
return new ResponseEntity<Set<Quiz>>(HttpStatus.NO_CONTENT);
}else{
return new ResponseEntity<Set<Quiz>>(quizs, HttpStatus.OK);
}
}
#RequestMapping(value = "/quiz/{id}", method = RequestMethod.GET, headers="Accept=*/*", produces="application/json")
public ResponseEntity<Quiz> quizById(#PathVariable("id") Long quizId) {
Quiz quiz = quizService.getQuizById(quizId);
if(quiz == null){
return new ResponseEntity<Quiz>(HttpStatus.NO_CONTENT);
}else{
return new ResponseEntity<Quiz>(quiz, HttpStatus.OK);
}
}
}
in success callback you are try to get id which is not exist in your page
replace this
$('#edit_quiz_title').val(data.quizTitle);
with this
$('#quiz_title').val(data.quizTitle);

AngularJs datatable dynamic table change

I am working on a project and i want to do some things which are new to me. I am new in AngularJS and newer in angular data tables.
I got angular data table from here and is a little bit tricky for me because i don't really know how to use it. Examples are not very explanatory for me.
What i want to do:
i have a sigle page with some checkboxes on the left
on the right i want a data table with data provided by server after user clicks on a checkbox
data table must change dinamicaly because depends on the request i have other headers for data table. For example when user click on "role" objects returned have only 2 fields id and role, i want to render role column but not id. When user clicks on "users" data returned by server has multiple objects which have much more fields, for example : "accNonExp", "accNonLocked", "email", "username" and others.
How can i do this ?
here is my conde right now :
js :
depo.controller('masterMainController', ['$scope', '$http', function ($scope, $http) {
$scope.listOfTables = null;
$scope.tableData = {};
$scope.onClick = function(){
$scope.tableData = getTableData($scope.valueSelected);
};
$http.post('/master/listOfTables').success(function (response) {
$scope.listOfTables = response;
console.log(response);
});
function getTableData(table) {
$http.post('/master/tableData/' + table).success(function (response) {
console.log(response);
return response;
});
}
$scope.dataTable = function(DTOptionsBuilder, DTColumnBuilder) {
var vm = this;
vm.dtOptions = DTOptionsBuilder.fromJson($scope.tableData)
.withPaginationType('full_numbers');
/* vm.dtColumns = [
DTColumnBuilder.newColumn('id').withTitle('ID'),
DTColumnBuilder.newColumn('firstName').withTitle('First name'),
DTColumnBuilder.newColumn('lastName').withTitle('Last name').notVisible()
];*/
}
}]);
JSP:
<%# include file="/WEB-INF/views/includes/onlyForLoggedUsers.jsp" %>
<html>
<head>
<title>Main Master</title>
</head>
<script content="text/javascript" src="/res/custom_script/admin/masterMain.js"></script>
<body ng-app="depo">
<div class="container-fluid" ng-controller="masterMainController">
<p class="logout_paragraph">Logged as <strong>${pageContext.request.userPrincipal.name}</strong> | <a
id="logout_link" onclick="formSubmit()">Logout</a></p>
<form action="/logout" method="post" id="logoutForm" style="display: none;">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>
<div class="jumbotron">
<h2>Welcome !</h2>
</div>
<div>
<div id="divChkListOfTables" class="admin_left_menu pre-scrollable col-md-2">
<div id="chkListOfTables" class="admin_tables_list radio">
<h4>Tables</h4>
<label ng-repeat="table in listOfTables.tables" class="admin_tables_list_chk_box">
<input type="radio" name="chkTablesRadio" ng-model="$parent.valueSelected" ng-change="onClick()"
ng-value="table" class="radio-button"> {{table}}
</label>
</div>
</div>
<div id="admin_data_table" class="col-md-10">
<table datatable="dataTable" dt-options="masterMainController.dtOptions" dt-columns="masterMainController.dtColumns" class="row-border hover">
</table>
</div>
</div>
</div>
</body>
</html>
Spring RestController:
#RestController
#RequestMapping(value = "/master")
public class MasterMainRest {
#Autowired
UnitService unitService;
#Autowired
RoleService roleService;
#Autowired
UsersService usersService;
#RequestMapping(value = "/listOfTables", method = RequestMethod.POST)
public MasterTablesDTO getListOfTables(){
List<String> tables = new ArrayList<>();
tables.add("unit");
tables.add("role");
tables.add("users");
MasterTablesDTO masterTablesDTO = new MasterTablesDTO();
masterTablesDTO.setTables(tables);
return masterTablesDTO;
}
#RequestMapping(value = "/tableData/{table}", method = RequestMethod.POST)
public List getTablesData(#PathVariable String table){
List list = null;
switch (table){
case "unit":
list = unitService.findAll();
break;
case "role":
list = roleService.findAll();
break;
case "users":
list = usersService.findAll();
break;
}
return list;
}
}
When i reach this page i gat this error :
TypeError: Cannot read property 'aDataSort' of undefined
at U (jquery.dataTables.min.js:63)
at xa (jquery.dataTables.min.js:67)
at HTMLTableElement.<anonymous> (jquery.dataTables.min.js:91)
at Function.n.extend.each (jquery-2.1.3.min.js:2)
at n.fn.n.each (jquery-2.1.3.min.js:2)
at m [as dataTable] (jquery.dataTables.min.js:83)
at h.fn.DataTable (jquery.dataTables.min.js:159)
at Object.g [as renderDataTableAndEmitEvent] (angular-datatables.min.js:6)
at Object.h [as doRenderDataTable] (angular-datatables.min.js:6)
at Object.d.render (angular-datatables.min.js:6)
Yes i know this error is beause $scope.tableData is empty, or this is what i read on some forums.
How can i make first checkbox checked and $scope.tableData loaded with data acording to that checkbox checked ?
Thank you in advance !
Since the getTableData(table) function isn't returning any value $scope.tableData is undefined as you mentioned. This is because of the AJAX request being asynchronous.
To fix this you have to supply a callback to the $http success where you fill the $scope.tableData. To learn more about promises checkout angulars documentation for the q implementation:
https://docs.angularjs.org/api/ng/service/$q
Something like this should fix it.
$scope.onClick = function(){
getTableData($scope.valueSelected).success(function(response) {
$scope.tableData = response.data
});
};
function getTableData(table) {
return $http.post('/master/tableData/' + table);
}

Load JSP file into Javascript to realize Fragments

I'm working with SringMVC and I'm searching for an easy solution to load a JSP into a div box of another JSP file. I heard about using Tiles but I would prefer to use ajax/jquery. Can anyone help me with that? I'm trying to get this working for two days now...
My current approach is something like this:
$(document).ready(function() {
var html = '<jsp:include page="searchSites.jsp"/>';
$('#contentbox').load(html);
});
But this is throwing an "Uncaught SyntaxError: Unexpected token ILLEGAL" Error at the second line. I also tried c:import but this isn't working, too.
Thank you very much for your help!
Edit:
#Controller
#RequestMapping("/search")
public class SearchController {
#Autowired private SiteService siteService;
#Autowired private SystemService systemService;
#RequestMapping(value = "")
public String displaySearch(Model model) {
return "displaySearch";
}
#RequestMapping(value = "sites", method = RequestMethod.POST )
public String displaySites(Model model, #RequestParam String searchStr) {
List<RSCustomerSiteViewDTO> sites = siteService.getSitesByName(searchStr);
model.addAttribute("sites", sites);
return "searchSites";
}
#RequestMapping(value = "systems", method = RequestMethod.POST)
public String displaySystems(Model model, #RequestParam String searchStr) {
List<RSServicedSystemViewDTO> systems = systemService.getSystemsByName(searchStr);
model.addAttribute("systems", systems);
return "searchSystems";
}
}
displaySearch.jsp
<html>
<head>
<title>Site</title>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<link rel="stylesheet" href="<c:url value="resources/css/style.css" />" />
<script>
$(document).ready(function() {
var html = '/crsp/search/sites';
$('#contentbox').load(html);
});
</script>
</head>
<body>
<div id="content">
<div id="searchdiv">
<form method="POST" action="search/sites">
<input type=text name=searchStr placeholder="Search Site..."
id="searchSite" class="search" />
</form>
<form method="POST" action="search/systems">
<input type=text name=searchStr placeholder="Search System..."
id="searchSystem" class="search" />
</form>
</div>
<div id="contentbox">
</div>
</div>
</body>
</html>
searchSites.jsp
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%# page session="false"%>
<table>
<tr id="header">
<td>Name</td>
<td>Customer</td>
<td>City</td>
<td>Region</td>
</tr>
<c:forEach var="site" items='${sites}' varStatus="loopStatus">
<tr class="${loopStatus.index % 2 == 0 ? 'even' : 'odd'}">
<td>${site.siteName}</td>
<td>${site.customerName}</td>
<td>${site.siteCity}</td>
<td>${site.regionName}</td>
</tr>
</c:forEach>
</table>
Edit:
I came closer. I have to fire something like this from the forms instead of the action which I got until now, then it will work: Suggestions?
function searchSites(searchStr) {
$.ajax({
type: "POST",
url: "sites?searchStr=",
success: function(data) {
$("#contentbox").html(data);
}
});
}
You should remove the JSP tag
var html = 'searchSites.jsp';
$('#contentbox').load(html);
The load method should be provided with a url that corresponds with a mapping to one of your controller methods.
Controller
#Controller
#RequestMapping("/site")
public class MyController{
#RequestMapping("/search")
public String getFragment(){
return "fragment";
}
}
Javascript
$(document).ready(function() {
var html = "/contextRoot/site/search"; //you may need to use jstl c:url for this
$('#contentbox').load(html);
});
Config
Please note this example, assumes you have a ViewResolver setup in your dispatcher configuration file as follows and there is a fragment.jsp file within the root of your WEB-INF directory:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/" />
<property name="suffix" value=".jsp" />
</bean>
The basic concept of request handling in Spring MVC is that a request is "somehow" mapped to a controller method. Spring MVC provides various ways of doing this url, request type, parameter presence, parameter values, etc... But basically it boils down to which controller/method should handle this request. This is most often accomplished using #RequestMapping.
After the method is found data binding occurs, meaning that request parameters are supplied to the method as arguments. Once again there are various ways to match parameters to arguments, including path variables, modelattributes, etc...
Next the body of the method is executed, this is pretty much custom and you provide the implementation.
The next part is where you seem to be getting stuck. The controller method next tells Spring what view should be displayed. Once again there are many ways to do this, but one of the most common is to return a String at the end of your method that corresponds with a view (.jsp). Usually a view resolver is registered to avoid hardcoding the name of a view file in the returned String. The returned String is resolved by the ViewResolver and associated view is returned.
To answer your follow up question if you want to serve the displaySearch.jsp after processing a request for search/systems you simply return that viewName.
#RequestMapping(value = "systems", method = RequestMethod.POST)
public String displaySystems(Model model, #RequestParam String searchStr) {
List<RSServicedSystemViewDTO> systems = systemService.getSystemsByName(searchStr);
model.addAttribute("systems", systems);
return "displaySearch";
}

Categories