Select tag always returns null - html

I am trying to create a search module to search shop details from database based on the criteria in select that user chooses
index.scala.html
#import helper._
#import helper.twitterBootstrap._
#main(Html("Home")) {
<!-- Main component for a primary marketing message or call to action -->
<div class="jumbotron">
<h1>Shop Directory</h1>
<p>Lets you search a nearby Shop and get to know their location</p>
<p>Search Shop by Product or Shop name</p>
<form class="form-inline" action="#routes.SearchController.search()" method="post">
<input type="text" class="form-inline input-lg" placeholder="Product/Shop name" name="keyword" required="keyword required">
<select class="form-inline input-lg" id="Select1" name="criteria">
<option value="">-:Select Criteria:- </option>
<option value="shop">Shop</option>
<option value="product">Product</option>
</select>
<button class="btn btn-lg btn-primary" role="button">Search</button>
</form>
</div>
}
Search.java
package viewmodels;
public class Search {
public String keyword;
public String criteria;
}
SearchResult.java
package viewmodels;
import models.Shop;
import play.mvc.Controller;
import java.util.ArrayList;
import java.util.List;
public class SearchResult extends Controller {
public String criteria;
public String keyword;
public List<Shop> shops;
public SearchResult() {
shops = new ArrayList();
}
}
SearchController.java
package controllers;
import models.Product;
import models.Shop;
import play.data.DynamicForm;
import play.data.Form;
import play.mvc.Controller;
import viewmodels.Search;
import viewmodels.SearchResult;
import java.util.List;
import play.mvc.Result;
import static play.data.Form.*;
public class SearchController extends Controller {
public static Result search() {
Form<Search> requestData = form(Search.class).bindFromRequest();
Search datatosearch = requestData.get();
// String criteria="shop";
String criteria = datatosearch.criteria;
SearchResult result = new SearchResult();
result.criteria = criteria;
result.keyword = datatosearch.keyword;
if (criteria == "shop") {
List<Shop> shops = Shop.findByShopName(datatosearch.keyword);
result.shops.addAll(shops);
}
else if (criteria == "product") {
List<Shop> shops = Product.findByShopName(datatosearch.keyword);
result.shops.addAll(shops);
}
return ok(views.html.search.results.render(result));
}
}
if I do String criteria="shop" or String criteria="product" in my SearchController.java then it works fine, meaning my model query is correct, but if I execute the above code with String criteria = datatosearch.criteria it shows a blank screen.
I am using play framework, I am really stuck at this and any help would be appreciated.

You are comparing strings with the == operator which is a no-no. Change your string comparisons to use String.equals so you are actually comparing the values instead of object references.
if (criteria.equals("shop") {
...
}
else if (criteria.equals("product") {
...
}
You probably also want to add some validation to check that criteria isn't NULL.

Related

How to initialize an external reference in Thymeleaf?

If I had a Java class called for instance Buffet and one of its fields was something like:
#ManyToOne
private Chef chef
and I had to create a new Buffet object in an html form using Thymeleaf, how would I be able to refer to this chef field? At the moment my html looks like this:
<form th:action="#{/newBuffet}" method="POST" th:object="${buffet}">
<div>
<div>
<span><input type="text" th:field="*{name}" placeholder="name"/></span>
</div>
<div>
<span><input type="text" th:field="*{chef}" placeholder="chef"/></span>
</div>
<div>
<span><button type="submit">Invio<i class="material-icons">done</i></button></span>
</div>
</div>
</form>
and my controller like this:
#RequestMapping(value = "/newBuffet", method = RequestMethod.GET)
public String formBuffet (Model model) {
model.addAttribute("buffet", new Buffet());
return "newBuffet.html";
}
#RequestMapping(value = "/newBuffet", method = RequestMethod.POST)
public String addBuffet (#ModelAttribute("buffet") Buffet b, Model model) {
this.buffetService.save(b);
model.addAttribute("buffets", this.buffetService.listBuffets());
return "buffets.html";
}
the error it gives is, of course, because of the way Thymeleaf's input takes only strings whilst my input is an instance of my class Chef.

How to set value to 2d array in input tag html

I am work in angular. I would like the user to be able to set up lesson subjects and a specific number of hours for a given student group.
group.component.html:
<!--list of groups -->
<div *ngFor="let group of groups">
<div><button (click)="Edit()">Edit group</button></div>
<!--mode without edit -->
<div *ngIf="edit==false">
<tr>Name:{{group.name}}</tr>
</div>
<!--mode with edit -->
<div *ngIf="edit==true">
<tr>Name:<input type="text" value="{{group.name}}" [(ngModel)]="group.name m[ngModelOptions]="{standalone: true}"></tr>
<!--add Subject and set amount hours -->
<!-- add one or more empty subject, select subject and set amount hours-->
<tr>Subjects:</tr>
<button (click)="addSubject()">add</button>
<!-- list of subjects for one group-->
<form>
<div *ngFor="let sub of yourSubjects; let i=index">
<select class="form-control">
{{group.name}}
<option *ngFor="let sub2 of subjectsList" value="{{sub2.name}}">{{sub2.name}}</option>
<input type="hide" [(ngModel)]="groupItem.subjects[[i][0]]" [ngModelOptions]="{standalone: true}">
</select>
<!-- set amount hours for one subject -->
<!--kind of lessons, for one subject -->
Lecture(h)<input type="text" [(ngModel)]="groupItem.subjects[[i][1]]" [ngModelOptions]="{standalone: true}">
workout(h)<input type="text" [(ngModel)]="groupItem.subjects[[i][2]]" [ngModelOptions]="{standalone: true}">
laboratory(h)<input type="text" [(ngModel)]="groupItem.subjects[[i][3]]" [ngModelOptions]="{standalone: true}">
<button (click)="deleteSubject()">Delete</button>
</div>
<!--send data to function -->
<input type="submit" value="Submit" (click)="Edit();updateGroup({id : group.id, name : group.name, yourAllSubjects : groupItem.subjects})">
</form>
</div>
</div>
group.component.ts:
import { Component, OnInit } from '#angular/core';
import {GroupsApiService, RoomsApiService, SubjectsApiService} from "../../../api.services";
import {Groups} from "../../../models/groups.model";
import {Subjects} from "../../../models/subjects.model";
#Component({
selector: 'app-group',
templateUrl: './group.component.html',
styleUrls: ['./group.component.css']
})
export class GroupComponent implements OnInit {
constructor(private groupsApiService:GroupsApiService, private subjectsApiService: SubjectsApiService) { }
groups:Groups[] = [] //list of groups from database
subjectsList:Subjects[]=[] //list of all subjects
groupItem:Groups = new Groups('',1) //one group object
subject:Subjects = new Subjects('',1) // one subject object
number:number = history.state?.data?.title // index one group from groups.component
ngOnInit(): void {
this.groupsApiService.getGroup(this.number).subscribe(data => this.groups = data);
this.subjectsApiService.getSubjects().subscribe(data=>this.subjectsList=data);
// get data from database, data of one group, data of subjects, function from apiservice
}
yourSubjects: Subjects[]=[]; //list of subject for one group
edit=false //say when edit mode on/off
//edit mode
Edit() {
this.edit = !this.edit;
}
// function in html, it send data to database
updateGroup({id, name, yourSubjects}: { id: number, name: string, yourAllSubjects: [][] }){
var arrStr = encodeURIComponent(JSON.stringify(yourSubjects));
this.groupsApiService.editGroup(id,name,arrStr).subscribe()
}
addSubject() {
this.yourSubjects.push(this.subject)
}
deleteSubject(){
this.yourSubjects.pop()
}
}
group.model.ts
export class Groups {
constructor(
public name: string,
public id: number,
public subjects:[][]
) { }
}
apiservice
#Injectable()
export class GroupsApiService {
constructor(private http: HttpClient) {
}
getGroups(): Observable<Groups[]> {
return this.http.get<Groups[]>(`${API_URL}/management/groups`)
}
editGroup(id:number,name: string, yourSubjects?:string){
return this.http.get<Groups[]>(`${API_URL}/management/groups/group/editgroup?id=${id}&name=${name}&subjects=${yourSubjects}`)
}
getGroup(id:number): Observable<Groups[]> {
return this.http.get<Groups[]>(`${API_URL}/management/groups/group?id=${id}`)
}
}
Summary:
The user selects one group and can edit it. He can add specific subjects to it, then specify the number of hours for the types of lessons in a given subject. The number of hours is specified in three text inputs. Then the array saves itself. The array is to keep the names of the items and the individual hours. e.g:
groupItem.subjects[[i][0]]= physics
groupItem.subjects[[i][1]] = 11
groupItem.subjects[[i][2]] = 12
groupItem.subjects[[i][3]] = 30
groupItem.subjects = [{'physics','11','20','30'},{'math','11','20','30'},{'biology','11','20','30'}]
In html have function:
```
<input type="submit" value="Submit" (click)="Edit();updateGroup({id : group.id, name : group.name, yourAllSubjects : groupItem.subjects})">
and in groyp.component.ts:
```
updateGroup({id, name, yourSubjects}:{ id: number, name: string, yourAllSubjects: string[][] })
{ var arrStr = encodeURIComponent(JSON.stringify(yourSubjects)); this.groupsApiService.editGroup(id,name,arrStr).subscribe()
}
Next url is send to backend. Unfortunalety i have null in subject:
http://localhost:5000/management/groups/group/editgroup?id=6&name=example&subjects=[]'
what to do to send arrays correctly in url?

How to Update a record in spring boot and mysql

I am a newbie to spring boot.I have created a crud operation and the insert operation is working properly. I have a challenge on the update operation , the program is giving an error on the web page
Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback.Wed Jul 22 20:39:03 CAT 2020 There was an unexpected error (type=Bad Request, status=400)
and the following error from the console
Resolved [org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'long'; nested exception is java.lang.NumberFormatException: For input string: "saveEmployee"]
how can I solve the problem?
my code is below
Controller Class
```
package com.zimprogrammer.springboot.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import com.zimprogrammer.springboot.model.Employee;
import com.zimprogrammer.springboot.service.EmployeeService;
#Controller
public class EmployeeController {
#Autowired
private EmployeeService employeeService;
#GetMapping("/")
public String vieHomePage(Model model) {
// this shows a list of employees
model.addAttribute("listEmployees", employeeService.getAllEmployees());
return "index";
}
#GetMapping("/showEmployeeForm")
public String showEmployeeForm(Model model){
//request for the form to enter the data
Employee employee =new Employee();
model.addAttribute("employee", employee);
return "new_employee";
}
#PostMapping("/saveEmployee")
public String saveEmployee(#ModelAttribute("employee") Employee employee) {
//save data to the database
employeeService.saveEmployee(employee);
return "redirect:/";
}
#GetMapping("/showFormForUpdate/{id}")
public String showFormForUpdate(#PathVariable( value="id") long id, Model model) {
//get the employee from the service
Employee employee =employeeService.getEmployeeById(id);
// set the employee to pre-populate the form
model.addAttribute("employee", employee);
return "update_employee";
}
}```
Employee Service Interface
```package com.zimprogrammer.springboot.service;
import java.util.List;
import com.zimprogrammer.springboot.model.Employee;
public interface EmployeeService {
List<Employee> getAllEmployees();
void saveEmployee(Employee employee);
Employee getEmployeeById(long id);
}
```
Employee Service Class
```
package com.zimprogrammer.springboot.service;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zimprogrammer.springboot.model.Employee;
import com.zimprogrammer.springboot.repository.EmployeeRepository;
#Service
public class EmployeeServiceImpl implements EmployeeService{
#Autowired
private EmployeeRepository employeeRepository;
#Override
public List<Employee> getAllEmployees() {
return employeeRepository.findAll();
}
#Override
public void saveEmployee(Employee employee) {
this.employeeRepository.save(employee);
}
#Override
public Employee getEmployeeById(long id) {
Optional<Employee> optional=employeeRepository.findById(id);
Employee employee=null;
if(optional.isPresent()) {
employee=optional.get();
}else {
throw new RuntimeException("User not found for id::" + id);
}
return employee;
}
}
```
Employee Repository Interface
```
package com.zimprogrammer.springboot.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.zimprogrammer.springboot.model.Employee;
#Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long>{
}
```
Update Form : Thymeleaf and bootstrap
```
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Employee Management System</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
</head>
<body>
<div class="container" style="width:40%; height:40%;">
<h1>Employee Management system</h1>
<hr>
<h2>Update Employee</h2>
<form action="#" th:action="#{saveEmployee}" th:object="${employee}"
method="POST">
<input type="hidden" th:field="*{id}" />
<input type="text" th:field="*{firstName}"
class="form-control mb-4 col-4">
<input type="text" th:field="*{lastName}"
class="form-control mb-4 col-4">
<input type="text" th:field="*{email}"
class="form-control mb-4 col-4">
<button type="submit" class="btn btn-info col-2">Update
Employee</button>
</form>
<hr>
<a th:href = "#{/}"> Back to Employee List</a>
</div>
</body>
</html>
```
Can you also post you entity class?
From the error it is telling that the required type is long but it is getting it as string? It may be possible that you have mentioned your id as string instead of long.
Also try to add th:action="#{/saveEmployee}" to be exact as that of your /saveEmployee endpoint
Add "/" in form th:action, like so -> th:action="#{/saveEmployee}"
Also check your crud repository, insted of long use Long.
I solved the problem
I added a / to make th:action="#{/saveEmployee}" and changed long to Long in my controller Class in the following request
#GetMapping("/showFormForUpdate/{id}")
public String showFormForUpdate(#PathVariable( value="id") Long id, Model model) {
//get the employee from the service
Employee employee =employeeService.getEmployeeById(id);
// set the employee to pre-populate the form
model.addAttribute("employee", employee);
return "update_employee";
}
and this solved the problem

Passing an array of ints from my HTML to Controller with Thymeleaf and SpringBoot

I am trying to pass an array of ints from my HTML back to my controller.
My flow is as follows:
I am retrieving data from an API and converting it to an Entity. All works fine.
However, I pass this to my HTML (Thymeleaf) and display some of the values to the User.
They then select one of the options and this is passed back to my Controller.
It is at this stage I lose the data I need.
In my Entity, I get the following data which I pass to the View (Example Below):
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "MOVIE_ID")
private long movieId;
#JsonProperty("title")
#Column(name = "TITLE")
private String title;
#JsonProperty("overview")
#Column(name = "OVERVIEW", length = 2000)
private String overview;
#JsonProperty("popularity")
#Column(name = "POPULARITY")
private float popularity;
#JsonProperty("release_date")
#Column(name = "RELEASE_DATE")
private String releaseDate;
#JsonProperty("genre_ids")
private int[] genreIds;
Then in my view, I display some values and hide the ids I dont need to display so that I can pass them back to my controller:
<form action = "#" th:action="#{/saveMovie}" method="post" th:object="${movie}">
<tr>
<td th:text="${movie.title}"></td>
<td th:text="${movie.releaseDate}"></td>
<td th:text="${movie.overview}"></td>
<input type="hidden" id="title" name="title" th:value="*{title}"/>
<input type="hidden" id="overview" name="overview" th:value="*{overview}"/>
<input type="hidden" id="popularity" name="popularity" th:value="*{popularity}"/>
<input type="hidden" id="releaseDate" name="releaseDate" th:value="*{releaseDate}"/>
<input type="hidden" id="genreIds" name="genreIds" th:value="*{genreIds}"/>
<td>
<div class="col-auto">
<button class="btn btn-primary" type="submit">Add</button>
</div>
</td>
</tr>
</form>
Controller to handle the call:
#PostMapping("/saveMovie") public String saveMovie(#ModelAttribute(value = "movie") Movie movie)
UPDATE***
Adding the GET/POST controllers that currently interact with this page:
#GetMapping("/searchMovie")
public String searchMovie(final Model model){
List<Movie> returnedMovies = new ArrayList<>();
model.addAttribute("movies", returnedMovies);
return "Search";
}
#PostMapping("/searchMovie")
public String searchMovieInTMDB(#RequestParam(value = "movieName", required = true) String movieName,
Model model){
List<Movie> returnedMovies = service.searchMovies(movieName);
model.addAttribute("movies", returnedMovies);
return "Search";
}
#PostMapping("/saveMovie")
public String saveMovie(#ModelAttribute(value = "movie") Movie movie){
service.storeMovie(movie);
return "WORK_IN_PROGRESS";
}
However, when I pass the values back to the controller I get the conversion error:
[Failed to convert property value of type 'java.lang.String' to required type 'int[]' for property 'genreIds']
I have changed it to String[] to test this works and error goes away but then I am presented with another problem in that it is converted to :
String Value Image
The only way I have found to pass the object back is by using the input tag and hiding them.
It converts the float fine, but can't handle the array of ints.
Is there a better way to pass objects back and forth between the controller using Thymeleaf or is there another attribute I can use to pass the array back and forth?
Thanks in advance
Conor
<form action="#" th:action="#{/saveMovie}" method="post"
th:object="${movie}">
<tr>
<td th:text="${movie.title}"></td>
<td th:text="${movie.releaseDate}"></td>
<td th:text="${movie.overview}"></td>
<input type="hidden" id="title" name="title" th:value="*{title}" />
<input type="hidden" id="overview" name="overview"
th:value="*{overview}" />
<input type="hidden" id="popularity" name="popularity"
th:value="*{popularity}" />
<input type="hidden" id="releaseDate" name="releaseDate"
th:value="*{releaseDate}" />
<input type="hidden" name="genreIds" th:field="*{genreIds}" />
<td>
<div class="col-auto">
<button class="btn btn-primary" type="submit">Add</button>
</div>
</td>
</tr>
</form>
#PostMapping("/saveMovie")
public String saveMovie(#ModelAttribute Movie movie) {
System.err.println(movie);
return "redirect:/movies";
}
#GetMapping("/movies")
public String getBooks(Model model) {
Movie movie = new Movie();
movie.setGenreIds(new int[] {4,5,6,7,8});
model.addAttribute("movie", movie);
return "movie";
}
Maybe You should send numbers as List to the controller.
#PostMapping("/saveMovie")
public String saveMovie(#RequestBody List<Movie> movies){
movieService.function_name(movies);
return "movies";
}
Another way to do this is using AJAX call to the controller. Just need to collect numbers as list in javascript and through ajax you should send array as json to controller. In controller you will parse them

How to use *Ngfor in an other *Ngfor

I am trying to create a checkbox for each element of an array "lesCriteres".
Then I want each of these checkboxes to be checked if its value is in the table "actif.lesCriteresActifs"
Here is the code I want but it does not work as I want
<div class="checkbox-inline" *ngFor="let l of lesCriteres">
<div *ngFor="let a of actif.lesCriteresActifs">
<label></label>
<input type="checkbox" (change)="onChangeEvent(l.code, $event.target.checked)" [checked]="a.critere.code==l.code"> {{l.code}}<br>
</div>
</div>
MODELS
actif model
import {TypeActif} from './model.type-actif';
import {CritereActif} from './model.critere-actif';
export class Actif{
ref: string;
nom: string = '';
type_actif: TypeActif = new TypeActif();
lesCriteresActifs: Array<CritereActif> = new Array<CritereActif>();
}
CritereActif model
import {Actif} from './model.actif';
import {LesCriteres} from './model.les-criteres';
import {LesValeurs} from './model.les-valeurs';
export class CritereActif{
id: number;
actif: Actif = new Actif();
critere: LesCriteres = new LesCriteres();
valeur: LesValeurs = new LesValeurs();
}
LesCriteres model
export class LesCriteres{
code: string = null;
nom: string = '';
}
RESULT
i have this when i execute my code :
but i want't something like this :
This should work (using includes() method, without additional *ngFor):
<div class="checkbox-inline" *ngFor="let l of lesCriteres">
<label></label>
<input type="checkbox" (change)="onChangeEvent(l.code, $event.target.checked)" [checked]="actif.lesCriteresActifs.includes(l)"> {{l.code}}<br>
</div>
About includes method: https://www.w3schools.com/jsref/jsref_includes_array.asp
EDIT:
This solution comes to mind.
In .ts file of your component, inside class declare a function:
containsCode = (code) => {
for (let a of this.actif.lesCriteresActifs) {
if (a.critere.code === code) {
return true
}
}
return false
Then in .html file:
<div class="checkbox-inline" *ngFor="let l of lesCriteres">
<label></label>
<input type="checkbox" (change)="onChangeEvent(l.code, $event.target.checked)" [checked]="containsCode(l.code)"> {{l.code}}<br>
</div>