Angular input form values only update after focus - html

I have an Angular app with this form named 'form' and this page also has another form in the same html called 'form' as well. The second form loads the row first values coming from the ngFor but the rest only load after I click inside the unloaded input. This might be because of the same name?
<div class="all">
<div class="card card-rounded shadow-sm">
<form [formGroup]="form">
<div class="p-3">
<div class="form-row">
<div class="form-group col-md-12">
<label>Tema</label>
<input [ngClass]="cssValidator(f.theme)" class="form-control" formControlName="theme">
<div *ngIf="f.theme.errors?.required && f.theme.touched" class="invalid-feedback">
Obrigatório
</div>
<div *ngIf="f.theme.errors?.maxlength" class="invalid-feedback">
Máximo 50 letras
</div>
</div>
</div>
</div>
</form>
</div>
<div class="card rounded shadow-sm mt-4" *ngIf="editMode">
<div class="p-3">
<div class="d-flex border-bottom">
</div>
<div class="form-row p-1">
<div [formGroup]="form" class="col">
<div formArrayName="details" *ngFor="let detail of details.controls; let i = index">
<fieldset [formGroupName]="i" class="form-group">
<div class="row">
<div class="form-group col-md-4">
<label>Preço</label>
<input [ngClass]="cssValidator(details.get(i+'.price'))" class="form-control" formControlName="price">
</div>
<div class="form-group col-md-4">
<label>Descrição</label>
<input [ngClass]="cssValidator(details.get(i+'.description'))"
class="form-control" formControlName="description" placeholder="Descrição...">
</div>
</div>
</fieldset>
<hr>
</div>
</div>
</div>
</div>
</div>
<br>
</div>
The ts:
get f(): any {
return this.form.controls;
}
get details(): FormArray {
return (this.form.get('details') as FormArray);
}
loadDetails() {
this.detailService.getDetailsByEventId(this.eventId).subscribe(
(detailsResult: Detail[]) => {
detailsResult.forEach(detail => {
this.details.push(this.createDetails(detail));
});
},
(error: any) => {
this.toastr.error('Erro ao tentar carregar detalhes', 'Erro!');
console.log(error);
}
).add(() => this.spinner.hide());
}

Related

Validation Condition In Angular

Hello I'm trying to submit data as per type. There 2 types 1.Answer 2.Sub Flow. But my save button not enabled when I'm selecting sub flow. Please help me What I'm missing there.
BELOW IS THE HTML FILE CODE
<div class="row">
<div class="box">
<app-question-error *ngIf="isError" [errorData]='errorData'></app-question-error>
<form *ngIf="!isError" [formGroup]="questionForm" (ngSubmit)="SubmitForm()">
<div class="col-12 col-md-8 col-sm-12">
<div>
<div class="form-group row">
<label for="colFormLabel" class="col-sm-3 col-form-label">Type </label>
<div class="col-sm-4 d-flex justify-content-between">
<select formControlName="subflow" class="form-control" (change)="onDropDownChange($event)">
<option>Answer</option>
<option>Subflow</option>
</select>
</div>
</div>
</div>
</div>
<div class="col-12 col-md-12 col-sm-12">
<div class="form-group row">
<div class="col-sm-2">
</div>
<div class="col-sm-10">
<div *ngIf="subflowSelection == 'Subflow'">
<ul class="list-group">
<ng-select [items]="flowNames" bindLabel="flowName" appendTo="body" multiple="true"
formControlName="subflow">
</ng-select>
</ul>
</div>
</div>
</div>
</div>
<ng-container *ngIf="subflowSelection === 'Answer'">
<div class="col-12 col-md-8 col-sm-12" formArrayName="answers">
<div *ngFor="let quantity of getAnswers().controls; let i=index" [formGroupName]="i">
<div class="form-group row">
<label for="colFormLabel" class="col-sm-3 col-form-label">{{mylabels.answer}} </label>
<div class="col-sm-9 d-flex justify-content-between">
<input type="text" class="form-control w-90" formControlName="answerText">
<span class="mr-2"></span>
<button (click)="removeAnswers(i)">
<i class="fa fa-minus" aria-hidden="true"></i>
</button>
</div>
</div>
</div>
<div class="col-sm-9 has-error" *ngIf="f.answers.touched && !f.answers.valid">
{{mylabels.answerRequired}}
</div>
<div>
</div>
</div>
<div class="col-12 col-md-8 col-sm-12">
<div class="form-group row">
<label for="colFormLabel" class="col-sm-3 col-form-label"> </label>
<div class="col-sm-9">
<div class="add-more-answers ">
<button type="button" (click)="addAnswers()"
class="col-12 col-md-5 col-sm-12 btn btn-blue">{{mylabels.add_more_ans}}</button>
</div>
</div>
</div>
</div>
</ng-container>
<div class="container">
<div class="col-md-12">
<div class="row d-flex justify-content-end">
<button [routerLink]="['/question-list']" type="button"
class="btn btn-gray btn-sm mr-4">{{mylabels.cancel}}</button>
<button type="submit" [disabled]="!questionForm.valid"
class="btn btn-red btn-sm ">{{mylabels.save}}</button>
</div>
</div>
</div>
</form>
Below is TS file code Where I'm creating form controls.
this.questionForm = this.fb.group({
questionText: ['', Validators.required],
questionHelp: '',
questionNote: '',
remarks:'',
multiAns: [false],
answers: this.fb.array([]),
subflow:'',
});
}
Above file is for Answer and Sub flow Drop down. Can anyone here who can help me for solving this issue. below is the screenshot for that save button.
1.Diabled Save Button after selecting sub flow option
2.Enabled Save Button after selecting Answer Option

save multiple rows into database usin dynamic input fields/larave and jQuery

I want to insert multiple rows from dynamic input fields.
So I'm using the following formm and the following script which adds dynamically input fields.
$(document).ready(function() {
$("body").on("click", ".add_new_frm_field_btn", function() {
var random = 1 + Math.floor(Math.random() * 1000); //generate random values..
var index = $(".form_field_outer").find(".form_field_outer_row").length + 1;
//added data-index and outer..class
$(".form_field_outer").append(`<div class="col-12 outer" data-index="${index}_${random}"><div class="card-body form_field_outer_row"> <div class="form-row"><div class="form-group col-md-4"> <label for="inputState">Casting</label><select id="id_casting" class="form-control" name="rows[${index}][id_casting]">
<option selected>Choose...</option><option data-id="{{$casting->id_casting}}" value="{{$casting->id_casting}}">{{$casting->nom.' '.$casting->prenom}}</option> </select></div><div class="form-group col-md-4"><label for="inputState">Type de contrat</label><select id="id_modele_contrat" class="form-control" name="rows[${index}][id_modele_contrat]"> <option selected>Choose...</option><option>...</option> </select></div><div class="card-body "><button type="button" class="btn btn-outline-warning mb-1 remove_node_btn_frm_field">Delete</button></div>
</div></div></div> `);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<div class="row">
<div class="col-12">
<div class="card mb-4">
<div class="card-body">
<h5 class="mb-4">Projet</h5>
<!-- <form id="projetform" method="post" action="ajout_projet" class="myForms" enctype="multipart/form-data"> -->
<form method="POST" id="projetform" class="myForms" enctype="multipart/form-data">
{{ csrf_field() }}
<input type="hidden" id="id_projet" name="id_projet" />
<div class="form-group">
<label for="inputAddress">Numéro de projet</label>
<input type="text" class="form-control" id="numero_projet" name="numero_projet" placeholder="Description">
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12 col-md-12 col-xl-8 col-left">
<div class="card mb-4">
<div class="card-body">
<button type="button" class="btn btn-outline-primary mb-1 add_new_frm_field_btn">Ajouter un nouveau casting</button>
</br>
</br>
<div class="row">
<div class="col-12">
<div class="card mb-4 form_field_outer ">
<div class="card-body form_field_outer_row outer" data-index="1">
<input type="hidden" id="id_projet_casting" name="id_projet_casting" />
<div class="form-row">
<div class="form-group col-md-4">
<label for="inputState">Casting</label>
<select class="form-control" name="rows[1][id_casting]" id="id_casting">
<option selected>Choose...</option>
#foreach($castings as $casting)
<option data-id="{{$casting->id_casting}}" value="{{$casting->id_casting}}">{{$casting->nom.' '.$casting->prenom}}</option>
#endforeach
</select>
</div>
<div class="form-group col-md-4">
<label for="inputState">Type de contrat</label>
<select id="id_modele_contrat" class="form-control" name="rows[1][id_modele_contrat]">
<option selected>Choose...</option>
#foreach($models_contrat as $model_contrat)
<option data-id="{{$model_contrat->id_modele_contrat}}" value="{{$model_contrat->id_modele_contrat}}">{{$model_contrat->modele_contrat}}</option>
#endforeach
</select>
</div>
<div class="card-body ">
<button type="button" class="btn btn-outline-warning mb-1 remove_node_btn_frm_field">Delete</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-12 col-md-12 col-xl-4 col-right">
<div class="card mb-4 casting_details ">
<div class="card-body casting_details2 ">
<div class="d-flex flex-row mb-3 ">
<!-- Pictures ot the selected casting will come here-->
</div>
</div>
</div>
</div>
<button type="submit" name="submit" id="submit" class="btn btn-primary mb-1">Add</button>
</div>
Ajax code :
$('#submit').click(function(){
$.ajax({
url:"{{route('ajout_projet.store')}}",
method:"POST",
data:$('#projetform').serialize(),
type:'json',
success: function(e){
console.log(e)
},
error: function(error){
console.log(error)
}
});
});
I put in my controller :
$data = $request->input('rows');
dd($data);
When I add in my frontEnd for example 4 input fields that is four rows , the dd($data); shows only the first row :
array:1 [
1 => array:2 [
"id_casting" => "19"
"id_modele_contrat" => "1"
]
]
while it should show the 4 additional input fields values like :
array:4 [
1 => array:2 [
"id_casting" => "19"
"id_modele_contrat" => "1"
],
2 => array:2 [
"id_casting" => "19"
"id_modele_contrat" => "1"
],
........
]
I tries many solutions but it stills the same problem n it takes only the first row in consideration and not all the additional input fields.
I am stuck in this point for a week and do not know what to do yet.
what i know is the problem is in my html or jquery code but i don't know exactly what is triggering this problem.
please help
UPDATE
migration files :
public function up()
{
Schema::create('projets', function (Blueprint $table) {
$table->increments('id_projet');
$table->string('numero_projet',10);
}
public function up()
{
Schema::create('projets_castings', function (Blueprint $table) {
$table->increments('id_projet_casting');
$table->integer('id_projet')->nullable()->unsigned();
$table->integer('id_casting')->nullable()->unsigned();
$table->integer('id_contrat')->nullable()->unsigned();
$table->integer('actif')->default('1');
$table->timestamps();
$table->foreign('id_projet')->references('id_projet')->on('projets');
$table->foreign('id_casting')->references('id_casting')->on('castings');
$table->foreign('id_contrat')->references('id_contrat')->on('contrats');
});
}
maybe that can help someone else
I solved my problem by changing my html to
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<form method="POST" id="projetform" class="myForms" enctype="multipart/form-data">
{{ csrf_field() }}
<div class="row">
<div class="col-12">
<div class="card mb-4">
<div class="card-body">
<h5 class="mb-4">Projet</h5>
<!-- <form id="projetform" method="post" action="ajout_projet" class="myForms" enctype="multipart/form-data"> -->
<input type="hidden" id="id_projet" name="id_projet" />
<div class="form-group">
<label for="inputAddress">Numéro de projet</label>
<input type="text" class="form-control" id="numero_projet" name="numero_projet" placeholder="Description">
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12 col-md-12 col-xl-8 col-left">
<div class="card mb-4">
<div class="card-body">
<button type="button" class="btn btn-outline-primary mb-1 add_new_frm_field_btn">Ajouter un nouveau casting</button>
</br>
</br>
<div class="row">
<div class="col-12">
<div class="card mb-4 form_field_outer ">
<div class="card-body form_field_outer_row outer" data-index="1">
<input type="hidden" id="id_projet_casting" name="id_projet_casting" />
<div class="form-row">
<div class="form-group col-md-4">
<label for="inputState">Casting</label>
<select class="form-control" name="rows[1][id_casting]" id="id_casting">
<option selected>Choose...</option>
#foreach($castings as $casting)
<option data-id="{{$casting->id_casting}}" value="{{$casting->id_casting}}">{{$casting->nom.' '.$casting->prenom}}</option>
#endforeach
</select>
</div>
<div class="form-group col-md-4">
<label for="inputState">Type de contrat</label>
<select id="id_modele_contrat" class="form-control" name="rows[1][id_modele_contrat]">
<option selected>Choose...</option>
#foreach($models_contrat as $model_contrat)
<option data-id="{{$model_contrat->id_modele_contrat}}" value="{{$model_contrat->id_modele_contrat}}">{{$model_contrat->modele_contrat}}</option>
#endforeach
</select>
</div>
<div class="card-body ">
<button type="button" class="btn btn-outline-warning mb-1 remove_node_btn_frm_field">Delete</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
<button type="submit" name="submit" id="submit" class="btn btn-primary mb-1">Add</button>
</div>

Update input type time based on updated FormControl using PatchValue or SetValue in Angular

I have a form group with 3 inputs. The first input is a time input and the other 2 are custom form components. I setup a form.patchValue which updates the form values as seen below, however it does not update the UI, the time input is still empty.
How can I use patchValue to update the input ?
this.scheduleAutoReportForm = new FormGroup(
{
reportAt: new FormControl( '12:00' , Validators.required),
days: new FormControl([],Validators.required),
email: new FormControl([],[Validators.required])
}
);
this.scheduleAutoReportForm.patchValue({
reportAt: '24:00',
days:["2","4"],
email: ['placeholder#gmail.com']
});
this.ref.detectChanges();
Update
I experimented and it turns out that the textbox gets updated but not the time.
<div class="modal-header">
<h4 class="h-primary modal-title">Schedule Auto Report</h4>
<mh1-icon-button [icon]="faTimes" [iconClasses]="['btn', 'btn-sm', 'mx-0']" iconSize="lg" (click)="closeModal()">
</mh1-icon-button>
</div>
<div class="modal-body card">
<!-- This is where the form starts -->
<form [formGroup]='scheduleAutoReportForm' (ngSubmit)='onSubmit()'>
<div class="row">
<div class="col-3">
<label for="reportAt" ><h5>Send Report At:</h5></label>
<input type="time" name='reportAt' formControlName='reportAt' class="form-control" required>
</div>
</div>
<div class="row">
<div class="col-3">
<label for="test" >test</label>
<input type="text" name='test' formControlName='test' class="form-control" >
</div>
</div>
<div class="row mt-2">
<div class="col-12">
<sentryx-day-selector formControlName="days"></sentryx-day-selector>
</div>
</div>
<div class="row mt-2">
<div class='col-12'>
<sentryx-email-chips formControlName="email"></sentryx-email-chips>
</div>
</div>
<div class="row mt-5">
<div class="col-12">
<button type="submit" class="btn btn-md btn-secondary"
[disabled]="!scheduleAutoReportForm.valid">Submit</button>
<button type="cancel" class="btn btn-md btn-secondary">Cancel</button>
</div>
</div>
</form>
</div>
<div class="modal-footer card">
{{scheduleAutoReportForm.value | json}}
{{schedule | json}}
</div>
Did you try calling updateValueAndValidity() after patching the value?
See
What is updateValueAndValidity

How to loop data into textarea thymeleaf?

Do you know how can we loop data into textarea in thymeleaf?
Please you help to me a sample or any suggestion to do this.
Thanks.
java code
#GetMapping("/import_billing")
public String getImportBilling(Model model) {
model.addAttribute("importBilling", new ImportBilling());
return "importBilling";
}
#PostMapping("/import_billing")
public String postImportBilling(ImportBilling request, Model model, BindingResult result) {
if (result.hasErrors()) {
for (FieldError error : result.getFieldErrors()) {
System.out.println(error.getField() + ": " + error.getDefaultMessage());
}
model.addAttribute("importBilling", request);
return "importBilling";
}
ApiResponse response = cardHolderService.importBillingData(request);
model.addAttribute("response", response.getData());
return "importBilling";
}
Html code
<div class="container-fluid" layout:fragment="content">
<div class="card shadow mb-4">
<div class="collapse show" id="collapseCardExample">
<div class="card-body">
<form class="page-information" th:action="#{/import_billing}" th:object="${importBilling}"
method="post">
<div class="row">
<div class="col-md-4">
<input type="number"
th:value="*{from}"/>
</div>
<div class="col-md-4">
<input type="number"
th:value="*{to}"/>
</div>
<div class="form-group col-md-4">
<button class="btn btn-primary" type="submit">
<i id="_spinner">Execute</i>
</button>
</div>
</div>
</form>
</div>
</div>
</div>
<label>Output console</label>
<div class="card shadow mb-4">
<div class="card-body">
<div class="chart-area">
<div class="form-group" th:each="temp:*{response}" >
<textarea class="form-control" id="exampleFormControlTextarea1" rows="5" th:text="${temp}"/>></textarea>
</div>
</div>
</div>
</div>
</div>
In this case, after on click button Execute I would like all response display in textarea
Use th:inline="text" and write your loop using textual syntax. For example, instead of:
<div class="form-group" th:each="temp:*{response}" >
<textarea class="form-control" id="exampleFormControlTextarea1" rows="5" th:text="${temp}"/>></textarea>
</div>
Do this:
<div class="form-group">
<textarea class="form-control" id="exampleFormControlTextarea1" rows="5" th:inline="text">
[# th:each="temp: *{response}"]
[[${temp}]]
[/]
</textarea>
</div>

ng-click not fire function in controller

The bug is very weird, I have been stucking here for hours just can find why my function in controller is fired.
Here is my HTML code:
<div class="col-md-9 clearfix" id="customer-account" ng-controller='ProfileController'>
<div class="box clearfix">
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label for="password_old">oldpassword</label>
<input type="password" class="form-control" id="password_old" ng-model="passwordold">
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label for="password_1">newpassword</label>
<input type="password" class="form-control" id="password_1" ng-model="passwordnew1">
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label for="password_2">retype</label>
<input type="password" class="form-control" id="password_2"ng-model="passwordnew2">
</div>
</div>
<p>{{passwordnew2}}</p>
</div>
<!-- /.row -->
<div class="text-center">
<button type="submit" class="btn btn-primary">
<i class="fa fa-save" ng-click="changePwd(passwordold,passwordnew1,passwordnew2)"></i> save
</button>
</div>
<div class="text-center" >
<p>{{errorMessageChangepwd}}aaaa</p>
</div>
</div>
</div>
After I click the Button, which ng-click attribute as you can see, nothing happen.
Here is my controller code:
controller('ProfileController', ['$scope','UserFactory','SharedDataFactory',
function($scope,UserFactory,SharedDataFactory){
$scope.user = UserFactory.user;
$scope.passwordold;
$scope.errorMessageChangepwd='error';
$scope.showErrMsgChangepwd = false;
$scope.passwordnew1;
$scope.passwordnew2;
$scope.changePwd = function(passwordold,passwordnew1,passwordnew2){
console.log("aaaaaaaaaa");
if (passwordnew1!==passwordnew2){
$scope.showErrMsgChangepwd= true;
$scope.errorMessageChangepwd = 'error';
}else{
UserFactory.changePwd(passwordnew1)
.catch(function(err){
console.log(err.data);
}).then(function(response){
console.log(response);
});
}
};}]);
I called console.log("aaaaaaaaaa"); in the first line of my function, but after I click the button, nothing is shown on console.
And also
<div class="text-center" >
<p>{{errorMessageChangepwd}}aaaa</p>
</div>`
does not show error aaaa as expected but aaa on the browser.
what could be wrong?
Thanks.
You need to add ng-controller="ProfileController" in the top of your form.
Which looks like missing on your code.