角 PrimeNG。 PrimeFlex:输入字段的行为不符合预期

Posted

技术标签:

【中文标题】角 PrimeNG。 PrimeFlex:输入字段的行为不符合预期【英文标题】:Angular PrimeNG. PrimeFlex: input field not behaving as expected 【发布时间】:2019-11-12 01:43:45 【问题描述】:

我正在使用 PrimeNG 和 Primeflex 开发 Angular 7 应用程序。在尝试为基于表单的组件设置样式时,我遇到了 <input pInputText ...> 元素不尊重 prime-flex 样式(或至少不符合我的预期)的问题。

问题摘要

(变体 1)

我将<label><input> 元素都包含在两个嵌套的<div> 元素中,它们的样式分别为class="p-grid"class="p-col-*"

<div class="p-grid">
  <div class="p-col-8">
    <label for="description">Description</label><br/>
    <input id="description" pInputText formControlName="description">
  </div>
  <div class="p-col-4">
    <label for="numeric">Numeric</label><br/>
    <input id="numeric" pInputText formControlName="numeric">
  </div>
</div>

我期待&lt;input&gt; 字段随着可用空间而增长/缩小,但它似乎有一个固定的宽度,不适应可用空间或我正在使用的列数。

(变体 2)

然后我尝试在 column-div 中嵌套另一个 p-gridelement 并为每个元素提供全宽:

<div class="p-grid">
  <div class="p-col-8">
    <div class="p-grid">
    <label class="p-col-12" for="description">Description</label>
    <input class="p-col-12" id="description" pInputText formControlName="description">
  </div>
  </div>
  <div class="p-col-4">
    <div class="p-grid">
    <label class="p-col-12" for="numeric">Numeric</label>
    <input class="p-col-12" id="numeric" pInputText formControlName="numeric">
  </div>
  </div>
</div>

这确实使&lt;input&gt; 字段增长以使用可用的外部列空间,但以某种方式破坏了列/字段之间的边距。

(变体 3)

经过一些试验,我想出了一个可以满足我要求的解决方案,但它使用了不正确的主要 flex 类嵌套:

<div class="p-grid">
  <div class="p-col-8">
    <label class="p-col-12" for="description">Description</label>
    <input class="p-col-12" id="description" pInputText formControlName="description">
  </div>
  <div class="p-col-4">
    <label class="p-col-12" for="numeric">Numeric</label>
    <input class="p-col-12" id="numeric" pInputText formControlName="numeric">
  </div>
</div>

这可以让字段根据外部列配置增大/缩小大小,并保持字段/列之间的边距。但是,由于这似乎违反了我理解的 primeflex 的嵌套规则,我不确定这是否确实是正确的方法。

显示问题的详细工作示例

工作示例也可以在 stackblitz 上找到。

这是一个完整的工作示例,基于默认的 Angular 项目(使用 ng new demo 创建):

对 package.json 中依赖项的修改 (npm i --save primeflex primeicons primeng​​em>)

"primeflex": "^1.0.0-rc.1",
"primeicons": "^1.0.0",
"primeng": "^8.0.0-rc.1"

对 angular.json 的修改

        "styles": [
          'node_modules/primeicons/primeicons.css',
          'node_modules/primeng/resources/primeng.min.css',
          'node_modules/primeflex/primeflex.css',
          'node_modules/primeng/resources/themes/nova-light/theme.css',
          "src/styles.css"
        ],

app.module.ts

import  BrowserModule  from '@angular/platform-browser';
import  NgModule  from '@angular/core';
import FormsModule, ReactiveFormsModule from '@angular/forms';
import PanelModule from 'primeng/panel';
import AutoCompleteModule from 'primeng/autocomplete';
import BrowserAnimationsModule from '@angular/platform-browser/animations';

import  AppComponent  from './app.component';
import  ListComponent  from './list.component';
import  DetailComponent  from './detail.component';
import  LeftComponent  from './left.component';
import  RightComponent  from './right.component';

@NgModule(
  declarations: [
    AppComponent,
    ListComponent,
    DetailComponent,
    LeftComponent,
    RightComponent
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    PanelModule,
    AutoCompleteModule,
    FormsModule,
    ReactiveFormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
)
export class AppModule  

app.component.ts

import  Component  from '@angular/core';

@Component(
  selector: 'app-root',
  template: `
  <ng-container>
    <h3>Title</h3>
    <div class="container">
      <app-list></app-list>
      <app-detail></app-detail>
    </div>
  </ng-container>`,
  styles: [`
    div.container 
      display: flex;
      flex-wrap: nowrap;
    
    app-list 
      flex: 0 0 auto;
    
    app-detail 
      flex: 1 0 auto;
    `
  ]
)
export class AppComponent 
  title = 'demo';

list.component.ts

import  Component  from '@angular/core';

@Component(
  selector: 'app-list',
  template: `
  <p-panel [header]="'List'">
    <div class="item" *ngFor="let item of items">
        <div>item</div>
    </div>
  </p-panel>` 
)
export class ListComponent 
  items: string[] = ['Item 1', 'Item 2', 'Item 3'];

detail.component.ts

import  Component  from '@angular/core';

@Component(
  selector: 'app-detail',
  template: `
  <div class="left">
    <p-panel [header]="'Left'">
        <app-left></app-left>
    </p-panel>
  </div>
  <app-right></app-right>`,
  styles: [':host  display: flex;  div.left flex: 1 0 auto; padding: 0 15px;   app-right  flex: 0 1 50%; ']
)
export class DetailComponent 

left.component.ts

import  Component  from '@angular/core';

@Component(
  selector: 'app-left',
  template: '<p>left works!</p>'
)
export class LeftComponent 

right.component.ts

(通过取消注释正确的行来选择 right*.component.html 的哪个版本。这些的顺序对应于我在上面介绍我的三种方法时使用的顺序)

import  Component, OnInit  from '@angular/core';
import FormBuilder, FormGroup from '@angular/forms';

@Component(
  selector: 'app-right',
// --> choose variant by activating one of the three following lines
  templateUrl: './right1.component.html'
//  templateUrl: './right2.component.html'
//  templateUrl: './right3.component.html'
)
export class RightComponent implements OnInit 
  form: FormGroup;

  items: string[] = ['Austria','France','Germany','Italy','Liechtenstein','Switzerland'];

  constructor(private fb: FormBuilder)  

  ngOnInit() 
    this.form = this.buildForm();
    this.fillForm();
  

  buildForm(): FormGroup 
    return this.fb.group(
      id1: [value: '', disabled: true],
      id2: [value: '', disabled: true],
      id3: [value: '', disabled: true],
      auto: [value: '', disabled: true],
      description: [value: '', disabled: true],
      numeric: [value: '', disabled: true],
      field1: [value: '', disabled: true],
      field2: [value: '', disabled: true],
      field3: [value: '', disabled: true],
      field4: [value: '', disabled: true]
    );
  

  fillForm() 
    this.form.controls.id1.setValue('42');
    this.form.controls.id2.setValue('666');
    this.form.controls.id3.setValue('314152');
    this.form.controls.auto.setValue('Germany');
    this.form.controls.description.setValue('Short text');
    this.form.controls.numeric.setValue('2345');
    this.form.controls.field1.setValue('foo');
    this.form.controls.field2.setValue('bar');
    this.form.controls.field3.setValue('baz');
    this.form.controls.field4.setValue('Lorem ipsum dolor sit amet, consectetur adipiscing elit.');
  

right1.component.html变体 1

<p-panel [header]="'Right 1'">
  <form [formGroup]="form" class="container">

  <div class="p-grid">
      <div class="p-col-12">
        <label for="id">ID</label>
        <div>
          <input pInputText id="id" formControlName="id1">
          <input pInputText formControlName="id2">
          <input pInputText formControlName="id3">
        </div>
      </div>
    </div>


  <h3>Grouped Information</h3>
    <div class="p-grid">
      <div class="p-col-12">
        <label for="auto">Autocomplete</label>
        <p-autoComplete
          id="auto"
          formControlName="auto"
          [suggestions]="items"
          [style]="width: '100%'">
        </p-autoComplete>
      </div>
    </div>
    <div class="p-grid">
      <div class="p-col-8">
        <label for="description">Description</label><br/>
        <input id="description" pInputText formControlName="description">
      </div>
      <div class="p-col-4">
        <label for="numeric">Numeric</label><br/>
        <input id="numeric" pInputText formControlName="numeric">
      </div>
    </div>


    <h3>More grouped information</h3>
    <div class="p-grid">
      <div class="p-col-3">
        <label for="field1">Field 1</label><br/>
        <input id="field1" pInputText formControlName="field1">
      </div>
      <div class="p-col-3">
        <label for="field2">Field 2</label><br/>
        <input id="field2" pInputText formControlName="field2">
      </div>
      <div class="p-col-3">
        <label for="field3">Field 3</label><br/>
        <input id="field3" pInputText formControlName="field3">
      </div>
      <div class="p-col-3">
        <label for="field4">Field 4</label><br/>
        <input id="field4" pInputText formControlName="field4">
      </div>
    </div>
  </form>
</p-panel>

right2.component.html变体 2

<p-panel [header]="'Right 2'">
  <form [formGroup]="form" class="container">

  <div class="p-grid">
      <div class="p-col-12">
        <label for="id">ID</label>
        <div>
          <input pInputText id="id" formControlName="id1">
          <input pInputText formControlName="id2">
          <input pInputText formControlName="id3">
        </div>
      </div>
    </div>


  <h3>Grouped Information</h3>
    <div class="p-grid">
      <div class="p-col-12">
        <label for="auto">Autocomplete</label>
        <p-autoComplete
          id="auto"
          formControlName="auto"
          [suggestions]="items"
          [style]="width: '100%'">
        </p-autoComplete>
      </div>
    </div>
    <div class="p-grid">
      <div class="p-col-8">
        <div class="p-grid">
        <label class="p-col-12" for="description">Description</label>
        <input class="p-col-12" id="description" pInputText formControlName="description">
      </div>
      </div>
      <div class="p-col-4">
        <div class="p-grid">
        <label class="p-col-12" for="numeric">Numeric</label>
        <input class="p-col-12" id="numeric" pInputText formControlName="numeric">
      </div>
      </div>
    </div>


    <h3>More grouped information</h3>
    <div class="p-grid">
      <div class="p-col-3">
        <div class="p-grid">
        <label class="p-col-12" for="field1">Field 1</label>
        <input class="p-col-12" id="field1" pInputText formControlName="field1">
      </div>
      </div>
      <div class="p-col-3">
        <div class="p-grid">
        <label class="p-col-12" for="field2">Field 2</label>
        <input class="p-col-12" id="field2" pInputText formControlName="field2">
      </div>
      </div>
      <div class="p-col-3">
        <div class="p-grid">
        <label class="p-col-12" for="field3">Field 3</label>
        <input class="p-col-12" id="field3" pInputText formControlName="field3">
      </div>
      </div>
      <div class="p-col-3">
        <div class="p-grid">
        <label class="p-col-12" for="field4">Field 4</label>
        <input class="p-col-12" id="field4" pInputText formControlName="field4">
      </div>
      </div>
    </div>
  </form>
</p-panel>

right3.component.html变体 3

<p-panel [header]="'Right 3'">
  <form [formGroup]="form" class="container">

    <div class="p-grid">
      <div class="p-col-12">
        <label for="id">ID</label>
        <div>
          <input pInputText id="id" formControlName="id1">
          <input pInputText formControlName="id2">
          <input pInputText formControlName="id3">
        </div>
      </div>
    </div>


    <h3>Grouped Information</h3>
    <div class="p-grid">
      <div class="p-col-12">
        <label for="auto">Autocomplete</label>
        <p-autoComplete
          id="auto"
          formControlName="auto"
          [suggestions]="items"
          [style]="width: '100%'">
        </p-autoComplete>
      </div>
    </div>
    <div class="p-grid">
      <div class="p-col-8">
        <label class="p-col-12" for="description">Description</label>
        <input class="p-col-12" id="description" pInputText formControlName="description">
      </div>
      <div class="p-col-4">
        <label class="p-col-12" for="numeric">Numeric</label>
        <input class="p-col-12" id="numeric" pInputText formControlName="numeric">
      </div>
    </div>


    <h3>More grouped information</h3>
    <div class="p-grid">
      <div class="p-col-3">
        <label class="p-col-12" for="field1">Field 1</label>
        <input class="p-col-12" id="field1" pInputText formControlName="field1">
      </div>
      <div class="p-col-3">
        <label class="p-col-12" for="field2">Field 2</label>
        <input class="p-col-12" id="field2" pInputText formControlName="field2">
      </div>
      <div class="p-col-3">
        <label class="p-col-12" for="field3">Field 3</label>
        <input class="p-col-12" id="field3" pInputText formControlName="field3">
      </div>
      <div class="p-col-3">
        <label class="p-col-12" for="field4">Field 4</label>
        <input class="p-col-12" id="field4" pInputText formControlName="field4">
      </div>
    </div>
  </form>
</p-panel>

说明问题的屏幕截图

变体 1(不增长/缩小)

变体 2(增长/缩小但缺少边距)

变体 3(有效但嵌套无效)

【问题讨论】:

这可以使用一些 stackblitz 示例,有问题的代码量很难跟踪 @Xesenix:谢谢,我从未使用过 stackblitz,但我会尝试找出如何使用它并创建一个可运行的示例。 @Xesenix 这里是一个工作 stackblitz 示例的链接:stackblitz.com/edit/angular-mfrg2n 通过不正确的嵌套,您是否指的是 p-col 之前缺少的 p-grid 如果那是您的问题,您应该检查哪些样式添加了 p-grid 它添加了边距,使其内部的任何内容都使用完整的网格单元格宽度。在第一种情况下,网格单元内没有调整大小,因为您添加的类只是描述布局而不是该布局的内容应该如何表现。在进一步的示例中,您将布局更深地添加到表单结构中,以便它开始影响它。在第三个示例中,您刚刚选择不将布局扩展到其全宽,并且它不是不正确的只是不同的用例。 是的,通过不正确的嵌套,我将带有 p-col 类的内部元素称为外部 p-col 元素的直接子代。根据文档(以及之前的引导经验),我预计需要一个中间 p-grid。 【参考方案1】:

添加

style="width: 100%;"

到您在 right1.component.html 中的输入(或定义/使用宽度为 100% 的类),例如:

   <input id="description" style="width: 100%;" pInputText formControlName="description">

默认情况下输入是 size=20,并且不会占用 div 的宽度。 p-col div 正在适当增长,而不是其中的输入。

【讨论】:

以上是关于角 PrimeNG。 PrimeFlex:输入字段的行为不符合预期的主要内容,如果未能解决你的问题,请参考以下文章

是否可以隐藏 Primeng 日历中的输入字段?

为啥我不能阻止用户编辑 PrimeNG 表单字段值?

Angular2 PrimeNG 条件行格式

编辑值时输入失去焦点。使用 ngFor 和 ngModel。角5

primeng使用步骤

如何通过 CSS 设置无效 p-inputNumber PrimeNg 表单组件的红色边框?