我有一个 Angular 18 中的应用程序,其中一个页面包含材料日期选择器。
当我弹出日期选择器时,一切都很好,但是当我用左/右箭头或年份更改月份时,数据位于组件容器之外
这是我的配置
"dependencies": {
"@angular/animations": "^18.1.3",
"@angular/cdk": "^18.0.0",
"@angular/common": "^18.1.3",
"@angular/compiler": "^18.1.3",
"@angular/core": "^18.1.3",
"@angular/fire": "^18.0.1",
"@angular/forms": "^18.1.3",
"@angular/material": "^18.0.0",
"@angular/material-moment-adapter": "^18.0.0",
"@angular/platform-browser": "^18.1.3",
"@angular/platform-browser-dynamic": "^18.1.3",
"@angular/router": "^18.1.3",
"@ng-bootstrap/ng-bootstrap": "^17.0.0",
"@ngx-translate/core": "^15.0.0",
"@ngx-translate/http-loader": "^8.0.0",
"firebase": "^10.11.1",
"flag-icons": "^7.2.1",
"moment": "^2.30.1",
"ng-bootstrap": "^1.6.3",
"ngx-mat-select-search": "^7.0.6",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.3"
},
angular.json 中的样式声明
"styles": [
"src/styles.scss",
"@angular/material/prebuilt-themes/indigo-pink.css"
],
样式.css
/* You can add global styles to this file, and also import other style files */
html,
body {
height: 100%;
}
body {
margin: 0;
font-family: Roboto, "Helvetica Neue", sans-serif;
}
.menu-button-container {
/* Existing styles */
height: 100vh;
/* Set container height to 100% viewport height */
display: flex;
/* Enable Flexbox layout */
justify-content: center;
/* Center buttons horizontally */
align-items: center;
/* Center buttons vertically */
gap: 20px;
/* Space buttons horizontally */
flex-wrap: wrap;
/* Enable line wrapping */
align-content: flex-start;
/* Align rows at the top */
}
.menu-button {
height: 150px !important;
/* Increase button height */
width: 200px !important;
/* Increase button width */
font-size: 18px !important;
/* Increase font size as desired */
}
.menu-button-content {
display: flex;
/* Enable Flexbox */
flex-direction: column;
/* Arrange items vertically */
align-items: center;
/* Center items horizontally */
gap: 5px;
/* Add space between icon and text */
}
#text-page {
font-family: Georgia, serif;
font-size: 19px;
letter-spacing: -1px;
word-spacing: 0px;
color: #000000;
font-weight: normal;
text-decoration: none;
font-style: normal;
font-variant: normal;
text-transform: none;
text-align: center;
}
我的带有日期时间选择器的组件
<app-titre-page [titre]="'admin.people.ajouter.titre'" [introduction]="'admin.people.ajouter.introduction'"></app-titre-page>
<form [formGroup]="addPeopleForm" (ngSubmit)="validerCreationPeople()">
<div class="flex-container">
<div class="bloc-identite">
<div class="bloc-numero">
<mat-form-field class="full-width">
<mat-hint>{{ 'admin.people.ajouter.champNumero' | translate }}</mat-hint>
<input matInput placeholder="{{ 'admin.people.ajouter.champNumero' | translate }}" formControlName="numero" required>
<mat-error *ngIf="addPeopleForm.get('numero')?.invalid && addPeopleForm.get('numero')?.touched">
<ng-container *ngIf="addPeopleForm.get('numero')?.errors?.['required']">
{{ "admin.people.ajouter.champNumeroObligatoire" | translate }}
</ng-container>
<ng-container *ngIf="addPeopleForm.get('numero')?.errors?.['notNumeric']">
{{ "admin.people.ajouter.champNumeroNumerique" | translate }}
</ng-container>
</mat-error>
</mat-form-field>
</div>
<div class="bloc-nom-prenom">
<mat-form-field class="full-width">
<input matInput placeholder="{{ 'admin.people.ajouter.champNom' | translate }}" formControlName="nom" required>
<mat-error *ngIf="addPeopleForm.get('nom')?.invalid && addPeopleForm.get('nom')?.touched">
{{ "admin.people.ajouter.champNomObligatoire" | translate }}
</mat-error>
</mat-form-field>
<mat-form-field class="full-width">
<input matInput placeholder="{{ 'admin.people.ajouter.champPrenom' | translate }}" formControlName="prenom" required>
<mat-error *ngIf="addPeopleForm.get('prenom')?.invalid && addPeopleForm.get('prenom')?.touched">
{{ "admin.people.ajouter.champPrenomObligatoire" | translate }}
</mat-error>
</mat-form-field>
</div>
<div class="bloc-genre">
<mat-form-field class="full-width mat-form-field">
<mat-select formControlName="genre" required placeholder="{{ 'commun.genre' | translate }}">
<mat-option value="M">{{ "commun.masculin" | translate }}</mat-option>
<mat-option value="F">{{ "commun.feminin" | translate }}</mat-option>
</mat-select>
<mat-error *ngIf="addPeopleForm.get('genre')?.invalid && addPeopleForm.get('genre')?.touched">
{{ "admin.people.ajouter.champGenreObligatoire" | translate }}
</mat-error>
</mat-form-field>
</div>
<mat-form-field class="full-width mat-form-field">
<input matInput [matDatepicker]="picker" placeholder="{{ 'admin.people.ajouter.champNaissance' | translate }}" formControlName="dateNaissance">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker useUtc="false"></mat-datepicker>
</mat-form-field>
</div>
<div class="bloc-adresse">
<mat-form-field class="full-width">
<input matInput placeholder="{{ 'admin.people.ajouter.champAdresse' | translate }}" formControlName="adresse" [matAutocomplete]="auto">
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="selectionnerAdresse($event.option.value)">
<mat-option *ngFor="let result of resultatsRechercheAdresse" [value]="result">
{{ result.label }}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<mat-form-field class="full-width">
<input matInput placeholder="{{ 'admin.people.ajouter.champTelephone' | translate }}" formControlName="numeroTelephone">
<mat-error *ngIf="addPeopleForm.get('numeroTelephone')?.invalid && addPeopleForm.get('numeroTelephone')?.touched">
{{ "admin.people.ajouter.champTelephoneIncorrect" | translate }}
</mat-error>
</mat-form-field>
<mat-form-field class="full-width">
<input matInput placeholder="{{ 'admin.people.ajouter.champEmail' | translate }}" formControlName="email">
<mat-error *ngIf="addPeopleForm.get('email')?.invalid && addPeopleForm.get('email')?.touched">
{{ "admin.people.ajouter.champEmailIncorrect" | translate }}
</mat-error>
</mat-form-field>
</div>
</div>
<div class="button-container">
<button mat-raised-button color="primary" type="submit" [disabled]="addPeopleForm.invalid">
{{ "commun.enregistrer" | translate }}
</button>
<button mat-button color="warn" type="button" (click)="annulerCreationPeople()">
{{ "commun.annuler" | translate }}
</button>
</div>
</form>
CSS:
.full-width {
width: 100%;
max-width: 600px;
margin: 0 auto;
box-sizing: border-box;
}
.flex-container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin: 0 -16px;
}
.bloc-identite, .bloc-adresse {
width: 100%;
padding: 0 16px;
box-sizing: border-box;
}
@media (min-width: 768px) {
.bloc-identite, .bloc-adresse {
width: calc(50% - 32px); /* Chaque bloc occupe 50% de la largeur avec des marges */
}
}
.button-container {
display: flex;
justify-content: space-between;
padding: 16px;
box-sizing: border-box;
}
@media (max-width: 767px) {
.button-container {
flex-direction: column;
align-items: stretch;
}
.button-container button {
margin-bottom: 8px;
}
.button-container button:last-child {
margin-bottom: 0;
}
}
打字稿:
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { numericValidator } from '../../../app-validators';
import { PeopleService } from '../../../service/people.service';
import { Router } from '@angular/router';
import { debounceTime, distinctUntilChanged } from 'rxjs';
import { DataGouvService } from '../../../service/data-gouv.service';
import { People } from '../../../model/people';
import { TranslateService } from '@ngx-translate/core';
@Component({
selector: 'app-edit-people',
templateUrl: './edit-people.component.html',
styleUrl: './edit-people.component.scss'
})
export class EditPeopleComponent implements OnInit {
addPeopleForm!: FormGroup;
resultatsRechercheAdresse: any[] = [];
peopleAEditer: People | undefined;
constructor(
private fb: FormBuilder,
private peopleService: PeopleService,
private router: Router,
private dataGouvService: DataGouvService,
private traductionService: TranslateService,
) {
const navigation = this.router.getCurrentNavigation();
if (navigation?.extras.state) {
this.peopleAEditer = navigation.extras.state['people'];
}
}
ngOnInit(): void {
this.addPeopleForm = this.fb.group({
nom: [this.peopleAEditer?.nom || '', [Validators.required, Validators.minLength(3)]],
prenom: [this.peopleAEditer?.prenom || '', [Validators.required, Validators.minLength(3)]],
numero: [this.peopleAEditer?.numero || '', [Validators.required, numericValidator()]],
genre: [this.peopleAEditer?.genre || '', [Validators.required]],
dateNaissance: [this.peopleAEditer?.dateNaissance || '', []],
numeroTelephone: [this.peopleAEditer?.numeroTelephone || '', [Validators.pattern(this.traductionService.instant('admin.people.ajouter.champTelephoneFormat'))]],
email: [this.peopleAEditer?.email || '', [Validators.email]],
adresse: [this.peopleAEditer?.adresse, []]
});
// Abonnez-vous aux changements de valeur du champ de recherche avec debounceTime
this.addPeopleForm.get('adresse')?.valueChanges
.pipe(
debounceTime(300), // Attendre 300 millisecondes après la dernière frappe
distinctUntilChanged() // Ne déclencher que si la valeur a changé
)
.subscribe(value => {
this.rechercherAdresses(value);
});
}
annulerCreationPeople() {
this.router.navigate(['/admin/people']);
}
validerCreationPeople() {
if (this.addPeopleForm.valid) {
if (this.peopleAEditer) {
this.peopleService.mettreAJourPeople(this.addPeopleForm,this.peopleAEditer.uid ).then(() => {
// Une fois la promesse résolue, naviguez vers la route /admin/people
this.router.navigate(['/admin/people']);
});
} else {
this.peopleService.creerPeople(this.addPeopleForm).then(() => {
// Une fois la promesse résolue, naviguez vers la route /admin/people
this.router.navigate(['/admin/people']);
});
}
}
}
// Méthode appelée lorsque l'utilisateur sélectionne une suggestion
selectionnerAdresse(address: any) {
this.addPeopleForm.patchValue({
adresse: address.label
});
this.resultatsRechercheAdresse = []; // Réinitialise la liste des résultats après la sélection
}
rechercherAdresses(query: string) {
// Vérifie que query est une chaîne de caractères
if (typeof query === 'string' && query.trim() !== '') {
this.dataGouvService.searchAddress(query).subscribe(results => {
this.resultatsRechercheAdresse = results;
});
} else {
this.resultatsRechercheAdresse = []; // Réinitialise la liste des résultats si la requête est vide ou non valide
}
}
}
我认为这是 CSS 冲突,但我不明白是哪一个。你有什么想法吗?
请尝试以下代码:
HTML:
<mat-form-field class="example-full-width">
<mat-label>Choose a date</mat-label>
<input matInput [matDatepicker]="picker">
<mat-hint>MM/DD/YYYY</mat-hint>
<mat-datepicker-toggle matIconSuffix [for]="picker">
<mat-icon matDatepickerToggleIcon>keyboard_arrow_down</mat-icon>
</mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
ts 文件
import {provideNativeDateAdapter} from '@angular/material/core';
import {MatDatepickerModule} from '@angular/material/datepicker';
import {MatFormFieldModule} from '@angular/material/form-field';
import {MatIconModule} from '@angular/material/icon';
import {MatInputModule} from '@angular/material/input';
@Component({
selector: 'datepicker-custom-icon-example',
templateUrl: 'datepicker-custom-icon-example.html',
standalone: true,
providers: [provideNativeDateAdapter()],
imports: [MatFormFieldModule, MatInputModule, MatDatepickerModule, MatIconModule],