2
votes

I am attempting a dynamic form generator based on Angular's Dynamic Forms template using Angular 7 and I'm running into a css issue. I am using Bootstrap 4.0 and I hope it's not an issue where I need to go back to 3.0 (I had a prior issue that involved that, but correct re-coding got it to work in 4.0). If so, please let me know.

Now, here is the way that my app works correctly for my end product. My code to generate the drop downs is:

<div class="row">
  <div *ngFor="let question of questions" class="col-md-6 form-group">
    <label for="{{question.key}}">{{question.label}}</label>
    <span [ngSwitch]="question.controlType">
      <select *ngSwitchCase="'dropdown'"
        [id]="question.key"
        [formControlName]="question.key"
        [className]="question.fieldClass">
        <option *ngFor="let opt of question.options" [ngValue]="opt.value">{{opt.name}}</option>
      </select>
    </span>
    <span class="help-block error" *ngIf="isFormTouchedAndInvalid(question.key)">{{question.label}} is invalid</span>
  </div>
</div>

When this gets rendered to the screen, the drop downs are aligned correctly, with the correct widths, as you can see:

enter image description here

Now, if I follow Angular's method, my main code block will now become:

<div class="row">
  <app-question *ngFor="let question of questions" [question]="question" [form]="form"></app-question>
</div>

And my app-question component has the following code:

<div [formGroup]="form">
  <div class="col-{{question.colType}}-{{question.colWidth}} form-group">
    <label for="{{question.key}}">{{question.label}}</label>
    <span [ngSwitch]="question.controlType">
      <select *ngSwitchCase="'dropdown'"
        [id]="question.key"
        [formControlName]="question.key"
        [className]="question.fieldClass"
        >
        <option *ngFor="let opt of question.options" [ngValue]="opt.value">{{opt.name}}</option>
      </select>
    </span>
    <span class="help-block error" *ngIf="isFormTouchedAndInvalid(question.key)">{{question.label}} is invalid</span>
  </div>
</div>

When the form renders to the screen it looks like this:

enter image description here

As you can see, the column widths are gone. I'm certain it has something to do with the div tag holding the FormGroup attribute, but that is required for the component to compile and work. I've tried adding it with a span tag, adding the col-md-6 class to the same tag as FormGroup, but I get the same, incorrect CSS rendering.

Is this another Bootstrap 4 issue where I may need to go down to Bootstrap 3 for this to work? If not, what is going on and how can I get the page to correctly render like the first image and yet still be able to use the app-question component in my code?

1
As far as I remember bootstrap's row col definition looks for the row and a class col* right in a div underneath. But what speaks against adding the row class inside your question component where the formGroup-binding takes place or have you tried adding "row" as a class to you app-question tag?Erbsenkoenig

1 Answers

1
votes

I believe that the problem is that Angular renders app-question component as a tag <app-question></app-question> and your div tags inside of it have styles relative to that app-question tag, but not the parent <div class="row">. So if you add a class col-md-6(for example) it will cover 50% of the app-question tag, but not the row one.

So if you want the styles to work, you should add the classes here

<div class="row">
  <app-question *ngFor="let question of questions"
         [question]="question"
         [form]="form"
         class="col-md-6"> 
  </app-question>
</div>

As an alternative, you can change your app-question component decorator to make it an attribute.

@Component({
  selector: '[app-question]'
})

And then use it to any tag you like

<div class="row">
   <div app-question
        *ngFor="let question of questions"
        [question]="question"
        [form]="form"
        class="col-md-6"> 
   </app-question>
</div>