Я столкнулся с проблемой в моем коде. Я использую модальное диалоговое окно начальной загрузки. когда пользователь заполняет и отправляет форму, отображаемую в модальном окне, я хочу показать индикатор выполнения, чтобы информировать пользователя о том, что запрос обрабатывается. так вот код, который открывает модальное диалоговое окно.
cloneFlight() {
this.isLoading = true;
combineLatest(
this.translateService.get('CONFIRM.CLONE_FLIGHT', { item: this.flight.name}),
this.flightsService.getCampaignsToClone(this.flight)
).subscribe( ([header, campaigns]) => {
this.isLoading = false;
this.cloneFlightService.openModal(header,this.flight, campaigns);
});
}
CloneFlightService
@Injectable()
export class CloneFlightService
{
bsModalRef: BsModalRef;
constructor(private modalService: BsModalService, private flightService: FlightsService){}
openModal(header: string, flight: Flight, campaigns: CampaignUnpaginated[]) {
const initialState = {
flight: flight,
campaigns : campaigns,
header: header
};
this.bsModalRef = this.modalService.show(CloneFlightModalComponent,{ initialState});
}
}
CloneFlightModalComponent
@Component({
selector: 'pc-clone-flight-modal',
templateUrl: './clone-flight-modal.component.html',
styleUrls: ['./clone-flight-modal.component.scss']
}
)
export class CloneFlightModalComponent implements OnInit {
flight : Flight;
campaigns: CampaignUnpaginated[];
header: string;
formGroup: FormGroup;
compareResources = propComparator('id');
showCloneForm: boolean = true;
cloneSuccess:boolean = false;
cloneFailure:boolean = false;
isLoading:boolean = false;
constructor(public modalRef: BsModalRef, private fb: FormBuilder,
private flightService : FlightsService){
}
ngOnInit() {
this.formGroup = this.fb.group({
flightName: [{ value: ''},[Validators.required]],
campaign : [ '' , Validators.required]
});
this.showCloneForm = true;
}
handleSubmit(value: CloneFlightFormValue){
const cloneFlightRequest : CloneFlightRequest = {
flightName : value.flightName ,
campaignId : value.campaign.id,
flightId: this.flight.id ,
};
this.isLoading = false;
this.flightService.submitCloneFlight(cloneFlightRequest)
.subscribe( data => {
this.showCloneForm = false;
this.cloneSuccess = true;
this.cloneFailure = false;
this.isLoading = false;
},
err => {
this.showCloneForm = false;
this.cloneSuccess = false;
this.cloneFailure = true;
this.isLoading = false;
},
()=> {
this.showCloneForm = false;
this.isLoading = false;
}
);
}
}
Клон-летные modal.component.html
<ng-container *ngIf="showCloneForm">
<form [formGroup]="formGroup" (ngSubmit)="handleSubmit(formGroup.value)">
<pc-spinner [standalone]="true" *ngIf="true"></pc-spinner>
<pc-form-layout [showRequiredFieldsMessage]="false">
<div class="modal-header">
<h4 class="modal-title">
<fa-icon icon="clone"></fa-icon>
{{header}}
</h4>
</div>
<div class="modal-body-content">
<div class="inline-inputs-container">
<div class="inline-input ml-3">
<pc-form-field label="{{ 'LABELS.CLONE_FLIGHT' | translate }}" [required]="true" [errorMessages]="['required']">
<input type="text" formControlName="flightName" [placeholder]="'PLACEHOLDERS.CLONE_FLIGHT_NAME' | translate" ngModel>
</pc-form-field>
</div>
<div class="inline-input ml-3">
<pc-form-field label="{{ 'LABELS.CLONE_CAMPAIGN' | translate }}" [required]="true" [errorMessages]="['required']">
<select formControlName="campaign" [compareWith]="compareResources" ngModel>
<option value="" disabled> Please select a campaign </option>
<option *ngFor="let campaign of campaigns" [ngValue]="campaign"> {{campaign.name}} </option>
</select>
</pc-form-field>
</div>
</div>
</div>
<div class="modal-footer">
<pc-button theme="default" kind="flat" (click)="hideModal()">{{ 'ACTIONS.CANCEL' | translate }}</pc-button>
<pc-button theme="primary" type="submit" [disabled]="formGroup.invalid">{{ 'ACTIONS.CONFIRM' | translate }}</pc-button>
</div>
</pc-form-layout>
</form>
</ng-container>
<ng-container *ngIf="cloneSuccess">
<div class="modal-header">
<h4 class="modal-title">
<fa-icon icon="clone"></fa-icon>
Success
</h4>
</div>
<div class="modal-body-content ml-3">
<h5>
successfully cloned flight.
</h5>
</div>
<div class="modal-footer">
<pc-button theme="primary" (click)="hideModal()">{{ 'ACTIONS.CLOSE' | translate }}</pc-button>
</div>
</ng-container>
<ng-container *ngIf="cloneFailure">
<div class="modal-header">
<h4 class="modal-title">
<fa-icon icon="clone"></fa-icon>
FAILURE
</h4>
</div>
<div class="modal-body-content ml-3">
unable to clone flight:
</div>
<div class="modal-footer">
<pc-button theme="primary" (click)="hideModal()">{{ 'ACTIONS.CLOSE' | translate }}</pc-button>
</div>
</ng-container>
Клон-летные modal.component.scss
@import './../../../../scss/themes';
@import './../../../../scss/variables';
@import './../../../../scss/mixins';
.modal-header {
border-bottom: 0px;
}
.modal-title {
@include pc-page-title;
}
.close-btn {
color: $gray-600;
}
.modal-footer {
border-top: 0px;
}
компонент прядильщика.
import {Component, Input, HostBinding} из '@ angular / core';
@Component({
selector: 'pc-spinner',
templateUrl: './spinner.component.html',
styleUrls: ['./spinner.component.scss']
})
export class SpinnerComponent {
@Input() showBackdrop = true;
@Input()
@HostBinding('class.standalone')
standalone = false;
@Input()
@HostBinding('class.showMessage')
showMessage = false;
constructor() {}
}
spinner.component.html
<div *ngIf="showBackdrop && !standalone" class="backdrop"></div>
<div *ngIf="showMessage" class="message">
<div class="alert alert-info">
<ng-content></ng-content>
</div>
</div>
<div class="spinner">
<div class="circle circle1"></div>
<div class="circle circle2"></div>
<div class="circle circle3"></div>
</div>
spinner.component.scss
@import './../../../../scss/themes';
@import './../../../../scss/variables';
@import './../../../../scss/mixins';
:host {
&.standalone {
display: block;
position: relative;
width: 100%;
height: $spinner-standalone-height;
}
}
:host {
&.showMessage {
height: $spinner-show-message-height;
}
}
.backdrop {
z-index: $spinner-backdrop-z-index;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: $spinner-backdrop-bg-color;
border-radius: 4px;
}
.spinner {
width: 70px;
text-align: center;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
height: 20px;
margin: auto;
z-index: $spinner-z-index;
}
.circle {
width: 18px;
height: 18px;
@include themify() {
background-color: themed('brand-spinner');
}
border-radius: 100%;
display: inline-block;
animation: bounce 1.4s infinite ease-in-out both;
}
.spinner .circle1 {
animation-delay: -0.32s;
}
.spinner .circle2 {
animation-delay: -0.16s;
}
@keyframes bounce {
0%,
80%,
100% {
transform: scale(0);
}
40% {
transform: scale(1);
}
}
.message {
width: 100%;
display: flex;
position: absolute;
left: 0;
right: 0;
bottom: calc(50% + (#{$spinner-message-height} / 2));
height: $spinner-message-height;
z-index: $spinner-z-index;
}
.alert {
margin: 0px auto;
@include pc-dropshadow;
height: inherit;
&::before,
&::after {
content: '';
position: absolute;
}
&::before {
@include pc-equilateral-triangle('down', 9px, #cceefe);
bottom: -9px;
left: calc(50% - 9px);
z-index: $pc-info-popup-zindex-level-two;
}
&::after {
@include pc-equilateral-triangle('down', 10px, #b8e8fd);
bottom: -10px;
left: calc(50% - 9px);
z-index: $pc-info-popup-zindex-level-one;
}
}
это моя тема. Css
$themes: (
celcom:
(
brand-primary: #009ade,
brand-secondary: #fcba35,
brand-spinner: #009ade,
primary: #009ade,
secondary: #f3f3f3,
success: #119e5c,
danger: #d0021b,
warning: #fcba35,
info: lighten(#009ade, 5)
),
openmind:
(
brand-primary: #3d3d3d,
brand-secondary: #be233a,
brand-spinner: #be233a,
primary: #0277bd,
secondary: #f3f3f3,
success: #2e7d32,
danger: #be233a,
warning: #fb8c00,
info: lighten(#0277bd, 5)
),
du:
(
brand-primary: #00aace,
brand-secondary: #fcba35,
brand-spinner: #00aace,
primary: #00aace,
secondary: #f3f3f3,
success: #119e5c,
danger: #d0021b,
warning: #fcba35,
info: lighten(#009ade, 5)
)
);
@mixin themify($themes: $themes) {
@each $theme, $map in $themes {
:host-context(.theme-#{$theme}) & {
$theme-map: () !global;
@each $key, $submap in $map {
$value: map-get(map-get($themes, $theme), '#{$key}');
$theme-map: map-merge($theme-map, ($key: $value)) !global;
}
@content;
$theme-map: null !global;
}
}
}
@mixin themify-global($themes: $themes) {
@each $theme, $map in $themes {
.theme-#{$theme} & {
$theme-map: () !global;
@each $key, $submap in $map {
$value: map-get(map-get($themes, $theme), '#{$key}');
$theme-map: map-merge($theme-map, ($key: $value)) !global;
}
@content;
$theme-map: null !global;
}
}
}
@function themed($key) {
@return map-get($theme-map, $key);
}
Вкратце проблема в том, что компонент не виден в clone-flight-modal.component.html, поскольку стили не решаются из файла темы. компонент spinner и clone-flight-modal.component находятся в общем модуле моего углового приложения.
Вы можете видеть, что компонент изображения отображается без стиля
введите описание изображения здесь
это то, что я получил от инструмента разработчика для круга
.circle[_ngcontent-c9] {
width: 18px;
height: 18px;
border-radius: 100%;
display: inline-block;
-webkit-animation: bounce 1.4s infinite ease-in-out both;
animation: bounce 1.4s infinite ease-in-out both;
animation-duration: 1.4s;
animation-timing-function: ease-in-out;
animation-delay: 0s;
animation-iteration-count: infinite;
animation-direction: normal;
animation-fill-mode: both;
animation-play-state: running;
animation-name: bounce;
}
отсутствует цвет фона.
Также я могу видеть из инструментов разработчика Chrome, что не понимаю, пригодится ли он.
.standalone[_nghost-c13] {
display: block;
position: relative;
width: 100%;
height: 100px; }
.showMessage[_nghost-c13] {
height: 200px; }
.backdrop[_ngcontent-c13] {
z-index: 50;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.1);
border-radius: 4px; }
.spinner[_ngcontent-c13] {
width: 70px;
text-align: center;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
height: 20px;
margin: auto;
z-index: 51; }
.circle[_ngcontent-c13] {
width: 18px;
height: 18px;
border-radius: 100%;
display: inline-block;
-webkit-animation: bounce 1.4s infinite ease-in-out both;
animation: bounce 1.4s infinite ease-in-out both; }
.theme-celcom[_nghost-c13] .circle[_ngcontent-c13], .theme-celcom [_nghost-c13] .circle[_ngcontent-c13] {
background-color: #009ade; }
.theme-openmind[_nghost-c13] .circle[_ngcontent-c13], .theme-openmind [_nghost-c13] .circle[_ngcontent-c13] {
background-color: #be233a; }
.theme-du[_nghost-c13] .circle[_ngcontent-c13], .theme-du [_nghost-c13] .circle[_ngcontent-c13] {
background-color: #00aace; }
.spinner[_ngcontent-c13] .circle1[_ngcontent-c13] {
-webkit-animation-delay: -0.32s;
animation-delay: -0.32s; }
.spinner[_ngcontent-c13] .circle2[_ngcontent-c13] {
-webkit-animation-delay: -0.16s;
animation-delay: -0.16s; }
@-webkit-keyframes bounce {
0%,
80%,
100% {
-webkit-transform: scale(0);
transform: scale(0); }
40% {
-webkit-transform: scale(1);
transform: scale(1); } }
@keyframes bounce {
0%,
80%,
100% {
-webkit-transform: scale(0);
transform: scale(0); }
40% {
-webkit-transform: scale(1);
transform: scale(1); } }
.message[_ngcontent-c13] {
width: 100%;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
position: absolute;
left: 0;
right: 0;
bottom: calc(50% + (56px / 2));
height: 56px;
z-index: 51; }
.alert[_ngcontent-c13] {
margin: 0px auto;
-webkit-box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2);
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2);
height: inherit; }
.alert[_ngcontent-c13]::before, .alert[_ngcontent-c13]::after {
content: '';
position: absolute; }
.alert[_ngcontent-c13]::before {
border-left: 9px solid transparent;
border-right: 9px solid transparent;
border-top: 9px solid #cceefe;
bottom: -9px;
left: calc(50% - 9px);
z-index: 2; }
.alert[_ngcontent-c13]::after {
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid #b8e8fd;
bottom: -10px;
left: calc(50% - 9px);
z-index: 1; }
большое спасибо
Prasanth