I would like to add a css animation class to the ngb-modal-window element when the contained ReactiveForm is submitted and is invalid. What is the best practice for doing so?
Currently within my onStationEditSubmit() method I set my submitted property to true check the invalid property of my stationEdit:FormGroup property and if it is invalid I simply return but here is where I would like to also add the "shake" animation class on invalid.
Note: I would also like to make sure that if it is a second submission is invalid that I remove and add the animation class if necessary for the animation to occur again.
I do have a ViewChild ElementRef to the ng-template element passed to the injected NgbModal instance upon which the open method is called, but didn't know if it was possible to use that or the NgbModalRef returned from the NgbModal.open call to accomplish my goal.
Here is my component:
import { Component, OnInit, ViewChild, ElementRef } from '#angular/core';
import { NgbModal, NgbModalRef } from '#ng-bootstrap/ng-bootstrap';
import { NgBlockUI, BlockUI } from 'ng-block-ui';
import { FormGroup, FormBuilder, Validators, NgForm } from '#angular/forms';
#Component({
selector: 'app-stationedit',
templateUrl: './stationedit.component.html',
styleUrls: ['./stationedit.component.css']
})
export class StationEditComponent implements OnInit {
#BlockUI('basicModals') blockUIBasicModals: NgBlockUI;
#BlockUI('modalThemes') blockUIModalThemes: NgBlockUI;
#ViewChild('f', { read: true }) userProfileForm: NgForm;
#ViewChild('stationModalRef', { static: true }) stationModalRef: ElementRef;
stationEdit: FormGroup;
submitted = false;
stationModal: NgbModalRef;
constructor(private modalService: NgbModal, private formBuilder: FormBuilder) {
}
ngOnInit() {
console.log('In Station Edit');
this.stationEdit = this.formBuilder.group({
name: ['', Validators.required],
description: ['', Validators.required],
});
}
get f() {
return this.stationEdit.controls;
}
addNewStation(stationModalRef) {
this.modalService.open(stationModalRef, { windowClass: 'animated bounceInDown' });
}
onStationEditSubmit() {
this.submitted = true;
if (this.stationEdit.invalid) {
//I would like to shake the window on invalid submission by adding the "shake" class to the ngb-modal-window element
return;
}
}
}
Here is my template:
<div class="station-edit">
<!-- Station Edit start -->
<div class="form-group">
<!-- Button trigger modal -->
<button class="btn btn-lg btn-primary"
(click)="addNewStation(stationModalRef)">
Launch Modal
</button>
<!-- Modal -->
<ng-template class="modal text-left" #stationModalRef let-c="close" let-d="dismiss">
<div class="modal-header">
<h5 class="modal-title" id="stationModalTitle"><i class="la la-fw la-rocket"></i>Add New Station</h5>
<button type="button" class="close" aria-label="Close" (click)="d('Cross click')">
<span aria-hidden="true">×</span>
</button>
</div>
<form [formGroup]="stationEdit" (ngSubmit)="onStationEditSubmit()">
<div class="modal-body">
<div class="form-body">
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label for="stationName">Name *</label>
<input type="text" id="stationName" class="form-control" formControlName="name"
placeholder="Name" [ngClass]="{ 'is-invalid': submitted && f.name.errors }">
<div class="form-text text-muted danger invalid-feedback" *ngIf="submitted && f.name.errors">
<small *ngIf=" f.name.errors.required">
Name is required
</small>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label for="stationDescription">Description *</label>
<textarea id="stationDescription" rows="5" class="form-control" formControlName="description"
placeholder="Enter a Description for this station"
[ngClass]="{ 'is-invalid': submitted && f.description.errors }"></textarea>
<div class="form-text text-muted danger invalid-feedback" *ngIf="submitted && f.description.errors">
<small *ngIf=" f.description.errors.required">
Description is required
</small>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer form-actions">
<button type="button" class="btn btn-warning mr-1" (click)="d('Close modal')">
<i class="feather ft-x"></i> Cancel
</button>
<button type="submit" class="btn btn-primary" >
<i class="la la-check"></i> Save
</button>
</div>
</form>
</ng-template>
</div>
</div>
<!-- ////////////////////////////////////////////////////////////////////////////-->
In order to solve this I did the following:
used the native document.querySelector to get my nativeModalElement reference where required and used nativeModalElement.classList.remove and nativeModalElement.classList.add.
Added a shakeWindow() method to my component to add the headShake class on delay.
shakeWindow() {
const nativeModalElement = document.querySelector('ngb-modal-window.modal');
nativeModalElement.classList.add('headShake');
}
removed the animation classes that were present in my onStationEditSubmit class and used setTimeout to call the shakeWindow method delayed by 50ms.
onStationEditSubmit() {
this.submitted = true;
if (this.stationEdit.invalid) {
//Want to shake the window on invalid submission
const nativeModalElement = document.querySelector('ngb-modal-window.modal');
this.renderer.removeClass(nativeModalElement, 'headShake');
this.renderer.removeClass(nativeModalElement, 'fade');
this.renderer.removeClass(nativeModalElement, 'bounceInDown');
setTimeout(this.shakeWindow, 50);
return;
}
}
I cannot imagine this is the best practice approach so I would welcome a more opiniated Angular solution.
Note: I could not figure out how to use a QueryList or other ViewChild/ViewChildren method to accomplish this task.
Related
I have created a project for bookshop and in the section of employee information I want to upload a PDF file using code given below.it give me the below error.I have been trying since few days but I could not get the solution if there is any sample way please guide me
any help will be highly appreciated
The given data was invalid.","errors":{"file":["The file field is
required.
controller code is
public function store(Request $request)
{
$DocumentType= new DocumentType();
$this->validate($request,[
'name'=>'required',
'file' => 'required',
]);
$DocumentType->name = $request->input('name');
$fileName = time().'.'.$request->file->extension();
$request->file->move(public_path('Files'), $fileName);
$DocumentType->file = $name;
$DocumentType->save();
return response()->json($DocumentType);
}
Vue code is
<template>
<div class="container">
<div
class="modal fade"
id="addNew"
tabindex="-1"
role="dialog"
aria-labelledby="addNewLabel"
aria-hidden="true"
>
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" v-show="!editMode" id="addNewLabel">ثبت اسناد جدید</h5>
<h5 class="modal-title" v-show="editMode" id="addNewLabel">تمدید اسناد</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true" style="margin-right: 317px;">×</span>
</button>
</div>
<form
#submit.prevent="editMode ? updateDocumentType() : createDocumentType()"
enctype="multipart/form-data"
>
<div class="modal-body">
<div class="form-group">
<input
v-model="form.name"
placeholder="نام"
type="text"
name="name"
class="form-control"
:class="{ 'is-invalid': form.errors.has('name') }"
/>
<has-error :form="form" field="name"></has-error>
</div>
<div class="form-group">
<label for="file" class="col-sm-4 control-label">File</label>
<div class="col-sm-12">
<input
type="file"
class="form-input"
:class="{ 'is-invalid': form.errors.has('file') }"
id="file"
name="file"
/>
<has-error :form="form" field="file"></has-error>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal">لغو</button>
<button
v-show="editMode"
:disabled="form.busy"
type="submit"
class="btn btn-success"
>تمدید</button>
<button
v-show="!editMode"
:disabled="form.busy"
type="submit"
class="btn btn-primary"
>ثبت</button>
</div>
</div>
</form>
</div>
</div>
</div>
</template>
</div>
<script>
createDocumentType() {
// axios.get("api/getAllDocumentTypeDocumentType").then(response => {
// let data = response.data;
if (this.form.name == "") {
toast.fire({
type: "warning",
icon: "warning",
html: "<h5>نام لازم است.</h5>"
});
}
// else if (this.form.file == "") {
// toast.fire({
// type: "warning",
// icon: "warning",
// html: "<h5>لطفا،اسناد را انتخاب نماید.</h5>"
// });
// }
else {
this.form
.post("api/DocumentType")
.then(() => {
// the below function will be use to reload the page
// this.$emit("refreshPage");
$("#addNew").modal("hide");
toast.fire({
icon: "success",
type: "success",
html: "<h5> اسنادموافقانه اجاد گردید</h5>"
});
Fire.$emit("refreshPage");
this.form.reset();
// this.$Progress.finish();
})
.catch(er => {
console.log(er);
});
}
}
</script>
Migration table code
public function up()
{
Schema::create('document_types', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('file')->nullable();
$table->softDeletes();
$table->timestamps();
});
}
Code in API route
Route::apiResources(['DocumentType'=>'API\DocumentTypeController']);
Route::get('getAllDocumentType','API\DocumentTypeController#getAll');
The given data was invalid.","errors":{"file":["The file field is required. This error is because there is no existing file in your payload upon submission of your form.
in your form, bind data to your input file like what you did to your input name. like this
<input
type="file"
v-model="form.file"
class="form-input"
:class="{ 'is-invalid': form.errors.has('file') }"
id="file"
name="file"
/>
Or, attach an event to this file input and process the file provided. like this
<input
type="file"
class="form-input"
:class="{ 'is-invalid': form.errors.has('file') }"
id="file"
name="file"
#change="selectFile"
/>
Then in your methods, create also a selectFile function
methods: {
selectFile(file) {
if(file == "") return false
this.form.file = file.target.files
console.log(this.form.file)
}
}
I have login reactive form and added validations to form fields.
Once the user entered the value in form fields it should update the form value on the screen as I'm displaying form.value and also it should display the form status too. Both form value and status are not changing.
Nothing happened.
html
<div class="jumbotron">
<div class="container">
<div class="row">
<div class="col-md-6 offset-md-3">
<h2>Login</h2>
<form class='form' [formGroup]='loginForm' (ngSubmit)='onSubmit()' novalidate>
<div class="form-group">
<label for="username">Username</label>
<input type="text" class="form-control" id="username" placeholder="Username"/>
<div *ngIf="f.username.touched && f.username.errors" class="invalid-feedback">
<div *ngIf="f.username.errors.required">Username is required</div>
</div>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" id="password" placeholder="Password"/>
<div *ngIf="f.password.touched && f.password.errors" class="invalid-feedback">
<div *ngIf="f.password.errors.required">Password is required</div>
</div>
</div>
<div class="form-group">
<label><input type="checkbox"> Remember me</label>
</div>
<div class="form-group">
<button [disabled]="loginForm.invalid" class="btn btn-primary">Login</button>
</div>
</form>
<p>Form value: {{loginForm.value | json}}</p>
<p>Form value: {{loginForm.status | json}}</p>
</div>
</div>
</div>
</div>
ts file
import { ObjectMethod } from '#babel/types/lib';
import { AuthService } from './../auth.service';
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormGroup, FormControl, Validators } from '#angular/forms';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
loginForm: FormGroup;
returnUrl: string;
constructor(
private formBuilder: FormBuilder,
private authService: AuthService) { }
ngOnInit() {
this.loginForm = this.formBuilder.group({
username: ['', [ Validators.required]],
password: ['', [ Validators.required]]
});
}
//convenience getter for easy access to form fields
get f() {
return this.loginForm.controls;
}
onSubmit() {
console.log(this.loginForm.value);
/*Object.keys(this.loginForm.value).map(e => {
console.log(">>>>>>>",this.loginForm.value[e]);
});*/
this.authService.getUserDetails();
}
}
Because of form is invalid, login button is also not enabled.
Please help me in solving this.
You need to add formControlName to your inputs such as:
<div class="form-group">
<label for="username">Username</label>
<input type="text" class="form-control" id="username" formControlName="username" placeholder="Username"/>
<div *ngIf="f.username.touched && f.username.errors" class="invalid-feedback">
<div *ngIf="f.username.errors.required">Username is required</div>
</div>
</div>
For validity check I would use loginform.valid, this should return false when the form is invalid
I just learned vuejs with bootstrap 4 and I tried to display modal provided that when the create button was not clicked then the HTML modal tag is not displayed in the inspect element, and after the create button click bootstrap modal displayed. When the button create first time click HTML modal tag display on inspect element but bootstrap modal cannot be displayed on the browser page and the second time the bootstrap modal can be displayed. Here is the source code that I made with Laravel, can you help me on this issue, thank you.
User.vue
HTML
<template>
<div class="container">
<div class="row">
<div class="col-sm">
<div class="card-deck mb-3">
<div class="card mb-4 box-shadow">
<div class="card-header bg-success text-white">
<h4 class="my-0 font-weight-bold">
<!-- Button create user -->
<button #click="initAddUser()" class="btn btn-danger btn-sm"><i class="fa fa-plus"></i> Create New User</button>
<span class="float-right">User</span>
</h4>
</div>
<div class="card-body">
<!-- Bootstrap modal -->
<div v-if="showModal" class="modal fade" id="add_user_model" tabindex="-1" role="dialog" aria-labelledby="add_user_model_label" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header bg-info text-white">
<h5 class="modal-title" id="add_user_model_label"><i class="fa fa-plus"></i> Add New User</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<!-- Message errors create user -->
<div class="alert alert-danger" v-if="errors.length > 0">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
<h5>{{ messages }}</h5>
<ul>
<li v-for="error in errors">{{ error }}</li>
</ul>
</div>
<div class="form-group">
<label class="font-weight-bold" for="name">Name :</label>
<input type="text" class="form-control" id="name" name="name" placeholder="Name" v-model="user.name">
</div>
<div class="form-group">
<label class="font-weight-bold" for="name">Email :</label>
<input type="email" class="form-control" id="email" name="email" placeholder="E-mail" v-model="user.email">
</div>
<div class="form-group">
<label class="font-weight-bold" for="password">Password:</label>
<input type="password" class="form-control" id="password" name="password" placeholder="Password" v-model="user.password">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-sm btn-primary" #click="createUser()">Submit</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
Js
<script>
export default {
data() {
return {
user: {
name: '',
email: '',
password: ''
},
errors: [],
users: [],
showModal: false,
}
},
mounted() {
this.readUsers();
},
methods: {
initAddUser() {
this.errors = [];
$("#add_user_model").modal("show");
this.showModal = true;
},
reset() {
this.user.name = '';
this.user.email = '';
this.user.password = '';
},
readUsers() {
axios.get('/user/show')
.then(response => {
this.users = response.data.users;
});
},
createUser() {
axios.post('/user', {
name: this.user.name,
email: this.user.email,
password: this.user.password,
})
.then(response => {
this.reset();
this.users.push(response.data.user);
this.readUsers();
$("#add_user_model").modal("hide");
})
.catch(error => {
this.errors = [];
this.messages = error.response.data.message;
if (error.response.data.errors.name) {
this.errors.push(error.response.data.errors.name[0]);
}
if (error.response.data.errors.email) {
this.errors.push(error.response.data.errors.email[0]);
}
if (error.response.data.errors.password) {
this.errors.push(error.response.data.errors.password[0]);
}
});
}
}
}
</script>
Result images inspect element
This image button first time click https://ibb.co/jKENbU
This image button second time click https://ibb.co/nRy4qp
This is the vuejs component for editing song info. the problem here is with tags.I cannot show the tags of the song in vue select for editing.
<template>
<div>
<a data-toggle="modal" :data-target="'#EditModal'+ modalid" #click="select(song)"><span title="edit" class="glyphicon glyphicon-pencil" ></span></a>
<a class=""><span title="delete" class="glyphicon glyphicon-trash"></span></a>
<!-- Modal for editing song tracks-->
<div class="modal fade" :id="'EditModal'+ modalid" tabindex="-1" role="dialog" aria-labelledby="EditModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="EditModalLabel">Edit Song</h5>
<button type="button" class="close" ref="closemodal" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form ref="uploadform">
<div class="form-group">
<div class="row">
<div class="col-md-12">
<div class="col-md-5">
<button type="button" #click="browseImage" class="btn btn-md btn-default">Choose image:</button>
<div id="image_previews">
<img ref='image' class="" v-bind:src="image" width="200px" height="200px" >
<input class="form-control-file" ref="imageinput" type="file" name="feature_image" #change="showImage($event)">
</div>
</div>
<div class="col-md-7">
<div class="form-group">
<label for="title">Song Title:</label>
<input type="text" v-model="esong.title" class="form-control" required maxlength="255">
</div>
<div class="form-group">
<label for="genre"> Genre (tag atleast one) </label>
<v-select :placeholder="'choose tag'" v-model="tagids" label="name" multiple :options="tags"></v-select>
</div>
<div class="form-group">
<label for="upload_type">Song Upload Type</label>
<select name="upload_type" v-model="esong.upload_type" class="form-control">
<option value="public">public( free )</option>
<option value="private">private( for sale )</option>
</select>
</div>
<div class="form-group">
<label for="message-text" class="col-form-label">Description:</label>
<textarea class="form-control" id="message-text" v-model="esong.song_description"></textarea>
</div>
<div class="form-group" v-if="private">
<label for="upload_type">Song price</label>
<input type="text" v-model="esong.amount" class="form-control" required maxlength="255">
</div>
</div>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" #click="edit">Save</button>
</div>
</div>
</div>
</div><!-- end of modal -->
</div>
</template>
<script>
import vSelect from 'vue-select'
export default {
props: ['song','modalid','index','tags'],
components: {vSelect},
mounted() {
},
watch: {
tagids() {
console.log('changed tagids value');
// this.value = this.tagsid;
}
},
computed: {
private() {
if(this.esong.upload_type == 'private') {
return true;
}
return false;
},
},
methods: {
select(song) {
console.log(song.title);
this.getTagIds(song);
},
edit() {
let formData = new FormData();
formData.append('title', this.esong.title);
formData.append('img', this.esong.img);
formData.append('description', this.esong.song_description);
formData.append('upload_type', this.esong.upload_type);
formData.append('amount', this.esong.amount);
formData.append('tags', JSON.stringify(this.tagids));
formData.append('_method', 'PUT');
axios.post('/artist/songs/' + this.esong.id, formData,{
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(response =>{
this.$refs.closemodal.click();
toastr.success('successfully edited song.');
this.$emit('update', {song:this.esong,index:this.index});
}).catch(error => {
console.log(error);
});
},
getTagIds(song) {
axios.post('/gettagids', song ).then(response =>{
this.tagids = response.data;
}).catch(error =>{
console.log(error);
});
},
browseImage() {
this.$refs.imageinput.click();
},
showImage(event) {
this.esong.img = event.target.files[0];
this.image = URL.createObjectURL(event.target.files[0]);
}
},
data() {
return {
esong: this.song,
tagids: {id:'', name:'', label:''},
name:'name',
image:this.song.image
}
}
}
</script>
<style scoped>
input[type="file"] {
display: none;
}
#image_previews {
border-radius: 5px;background-color: whitesmoke; width: 200px; height: 200px;
}
.btn{
border-radius: 0px;
}
</style>
here I cannot get the selected value that was inserted in my table. I wanted to show the tagged values for a song. I am able to get all object of tagged songs from axios post request but v-select doesn't shows the selected value retrieved from a table.
the object received from laravel is similar to the object provided in options which work well with v-select..but it doesn't show the same structure object provided to v-model..or should I provide other props. the document for vue select has not mentioned any of these things
I'm using ABP 2.1.2 and on a form I have some controls hidden in a <div> with an *ngIf but when the <div> is revealed the floating labels don't animate so the user's text is badly merged with the label text.
component.html
<div bsModal #createServiceProviderModal="bs-modal" class="modal fade" (onShown)="onShown()" tabindex="-1" role="dialog"
aria-labelledby="createDigitalAssetModal" aria-hidden="true" [config]="{backdrop: 'static'}">
<div class="modal-dialog">
<div #modalContent class="modal-content">
<div class="modal-header">
<button type="button" class="close" (click)="close()" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title">
<span>{{l("CreateNewServiceProvider")}}</span>
</h4>
</div>
<div id="identify" *ngIf="step == 'identify'">
<div class="modal-body">
<div class="row clearfix">
<div class="col-sm-12">
<div class="form-group form-float">
<div class="form-line">
<input materialInput id="emailAddress" type="email" name="EmailAddress" [(ngModel)]="serviceProvider.emailAddress" required class="validate form-control">
<label for="emailAddress" class="form-label">{{l("EmailAddress")}}</label>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button [disabled]="saving" type="button" class="btn btn-default waves-effect" (click)="close()">
{{l("Cancel")}}
</button>
<button class="btn btn-info waves-effect" (click)="findServiceProvider()">
{{l("Next")}}
</button>
</div>
</div>
<form *ngIf="active" #createServiceProviderForm="ngForm" id="frm_create_serviceProvider" novalidate (ngSubmit)="save()">
<div id="add" *ngIf="step == 'create'">
<div class="modal-body">
<div class="row clearfix">
<div class="col-sm-12">
<div class="form-group form-float">
<div class="form-line">
<input id="companyName" type="text" name="CompanyName" [(ngModel)]="serviceProvider.companyName" required class="validate form-control">
<label for="companyName" class="form-label">{{l("CompanyName")}}</label>
</div>
</div>
</div>
</div>
<div class="row clearfix">
<div class="col-sm-6">
<div class="form-group form-float">
<div class="form-line">
<input id="name" type="text" name="Name" [(ngModel)]="serviceProvider.name" required class="validate form-control">
<label for="name" class="form-label">{{l("Name")}}</label>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="form-group form-float">
<div class="form-line">
<input id="surname" type="text" name="Surname" [(ngModel)]="serviceProvider.surname" required class="validate form-control">
<label for="surname" class="form-label">{{l("Surname")}}</label>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="form-group form-float">
<div class="form-line">
<input id="emailAddress" type="text" name="emailAddress" [(ngModel)]="serviceProvider.emailAddress" disabled class="validate form-control">
<label for="emailAddress" class="form-label">{{l("EmailAddress")}}</label>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button [disabled]="saving" type="button" class="btn btn-default waves-effect" (click)="close()">
{{l("Cancel")}}
</button>
<button [disabled]="!createServiceProviderForm.form.valid || saving" type="submit" class="btn btn-primary waves-effect">
{{l("Save")}}
</button>
</div>
</div>
<div id="identify" *ngIf="step == 'confirm'">
<div class="modal-body">
<span class="text-success">{{l('ServiceProviderAlreadyExists')}}</span>
<br>
<table class="table">
<tr>
<td class="col-span-3"><label class="pull-right">{{l('Name')}}</label></td>
<td>{{serviceProvider.name}}</td>
</tr>
<tr>
<td><label class="pull-right">{{l('Surname')}}</label></td>
<td>{{serviceProvider.surname}}</td>
</tr>
<tr>
<td><label class="pull-right">{{l('Company')}}</label></td>
<td>{{serviceProvider.companyName}}</td>
</tr>
<tr>
<td><label class="pull-right">{{l('Email Address')}}</label></td>
<td>{{serviceProvider.emailAddress}}</td>
</tr>
</table>
</div>
<div class="modal-footer">
<button [disabled]="saving" type="button" class="btn btn-default waves-effect" (click)="close()">
{{l("Cancel")}}
</button>
<button [disabled]="!createServiceProviderForm.form.valid || saving" type="submit" class="btn btn-primary waves-effect">
{{l("Save")}}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
component.ts
import { Component, ViewChild, Injector, Output, EventEmitter, ElementRef } from '#angular/core';
import { ModalDirective } from 'ngx-bootstrap';
import { ServiceProviderServiceProxy, ServiceProviderDto } from '#shared/service-proxies/service-proxies';
import { AppComponentBase } from '#shared/app-component-base';
#Component({
selector: 'create-service-provider-modal',
templateUrl: './create-service-provider.component.html'
})
export class CreateServiceProviderComponent extends AppComponentBase {
#ViewChild('createServiceProviderModal') modal: ModalDirective;
#ViewChild('modalContent') modalContent: ElementRef;
#Output() modalSave: EventEmitter<any> = new EventEmitter<any>();
serviceProvider: ServiceProviderDto = new ServiceProviderDto({id: 0, isUser: false});
step: string = "identify";
active: boolean = false;
saving: boolean = false;
constructor(
injector: Injector,
private serviceProviderService: ServiceProviderServiceProxy,
) {
super(injector);
}
show(): void {
this.active = true;
this.modal.show();
this.serviceProvider = new ServiceProviderDto({id: 0, isUser: false});
this.step = "identify";
}
onShown(): void {
$.AdminBSB.input.activate($(this.modalContent.nativeElement));
}
save(): void {
this.saving = true;
this.serviceProviderService.create(this.serviceProvider)
.finally(() => { this.saving = false; })
.subscribe(() => {
this.notify.info(this.l('SavedSuccessfully'));
this.close();
this.modalSave.emit(null);
});
}
close(): void {
this.active = false;
this.modal.hide();
}
findServiceProvider(): void {
this.saving = true;
abp.ui.setBusy();
this.serviceProviderService.getUserAsProvider(this.serviceProvider.emailAddress)
.finally(() => {
this.saving = false;
abp.ui.clearBusy();
})
.subscribe((next) => {
console.log(next);
if (next.id !== undefined) {
this.serviceProvider = next;
this.step = "confirm";
}
else {
this.step = "create";
}
})
}
}
Issue
When this modal is displayed the variable step is set to "identify" and the first section is displayed where the user must capture the service provider's email address. When the user clicks 'Next' I check if the service provider already exists and then change step to either "create" or "confirm". When the div for creating a service provider is displayed the labels for the input don't animate
Presumably I must re-run some kind of animation script but I cannot figure out what. Please help!
I think the problem was that I needed to call onShown() after revealing the div