Skip to content
This repository has been archived by the owner on Jan 19, 2023. It is now read-only.

Commit

Permalink
Allow adding form into a modal component; added storybook
Browse files Browse the repository at this point in the history
Signed-off-by: GuessWhoSamFoo <foos@vmware.com>
  • Loading branch information
GuessWhoSamFoo committed Aug 31, 2020
1 parent 5bc2dc2 commit dc75c00
Show file tree
Hide file tree
Showing 9 changed files with 286 additions and 58 deletions.
3 changes: 3 additions & 0 deletions pkg/view/component/form.go
Expand Up @@ -614,6 +614,7 @@ func (ff *FormFieldHidden) UnmarshalJSON(data []byte) error {

type Form struct {
Fields []FormField `json:"fields"`
Action string `json:"action,omitempty"`
}

func (f *Form) MarshalJSON() ([]byte, error) {
Expand Down Expand Up @@ -651,6 +652,7 @@ func (f *Form) UnmarshalJSON(data []byte) error {
Error string `json:"error"`
Validators []string `json:"validators"`
} `json:"fields"`
Action string `json:"action,omitempty"`
}{}

err := json.Unmarshal(data, &x)
Expand Down Expand Up @@ -694,6 +696,7 @@ func (f *Form) UnmarshalJSON(data []byte) error {

f.Fields = append(f.Fields, ff)
}
f.Action = x.Action

return nil
}
Expand Down
33 changes: 17 additions & 16 deletions pkg/view/component/modal.go
Expand Up @@ -17,32 +17,34 @@ const (

// ModalConfig is a configuration for the modal component.
type ModalConfig struct {
Body Component `json:"body"`
//Form Form `json:"form,omitempty"`
Body Component `json:"body,omitempty"`
Form *Form `json:"form,omitempty"`
Opened bool `json:"opened"`
ModalSize ModalSize `json:"size,omitempty"`
}

// UnmarshalJSON unmarshals a modal config from JSON.
func (m *ModalConfig) UnmarshalJSON(data []byte) error {
x := struct {
Body TypedObject `json:"body"`
//Form Form `json:"form,omitempty"`
Opened bool `json:"opened"`
ModalSize ModalSize `json:"size,omitempty"`
Body *TypedObject `json:"body,omitempty"`
Form *Form `json:"form,omitempty"`
Opened bool `json:"opened"`
ModalSize ModalSize `json:"size,omitempty"`
}{}

if err := json.Unmarshal(data, &x); err != nil {
return err
}

var err error
m.Body, err = x.Body.ToComponent()
if err != nil {
return err
if x.Body != nil {
var err error
m.Body, err = x.Body.ToComponent()
if err != nil {
return err
}
}

//m.Form = x.Form
m.Form = x.Form
m.Opened = x.Opened
m.ModalSize = x.ModalSize
return nil
Expand All @@ -57,10 +59,9 @@ type Modal struct {
}

// NewModal creates a new modal.
func NewModal(title []TitleComponent, body Component) *Modal {
func NewModal(title []TitleComponent) *Modal {
return &Modal{
Base: newBase(TypeModal, title),
Config: ModalConfig{Body: body},
}
}

Expand All @@ -72,9 +73,9 @@ func (m *Modal) SetBody(body Component) {
}

// AddForm adds a form to a modal. It is added after the body.
//func (m *Modal) AddForm(form Form) {
// m.Config.Form = form
//}
func (m *Modal) AddForm(form Form) {
m.Config.Form = &form
}

// SetSize sets the size of a modal. Size is medium by default.
func (m *Modal) SetSize(size ModalSize) {
Expand Down
24 changes: 15 additions & 9 deletions pkg/view/component/modal_test.go
Expand Up @@ -16,33 +16,39 @@ func TestModal_SetBody(t *testing.T) {
}

func TestModal_SetSize(t *testing.T) {
tests := []struct{
name string
size ModalSize
tests := []struct {
name string
size ModalSize
expected *Modal
}{
{
name: "small",
size: ModalSizeSmall,
expected: &Modal{
Base: newBase(TypeModal, TitleFromString("modal")),
Config: ModalConfig{ModalSize: ModalSizeSmall},
Base: newBase(TypeModal, TitleFromString("modal")),
Config: ModalConfig{
ModalSize: ModalSizeSmall,
},
},
},
{
name: "large",
size: ModalSizeLarge,
expected: &Modal{
Base: newBase(TypeModal, TitleFromString("modal")),
Config: ModalConfig{ModalSize: ModalSizeLarge},
Base: newBase(TypeModal, TitleFromString("modal")),
Config: ModalConfig{
ModalSize: ModalSizeLarge,
},
},
},
{
name: "extra large",
size: ModalSizeExtraLarge,
expected: &Modal{
Base: newBase(TypeModal, TitleFromString("modal")),
Config: ModalConfig{ModalSize: ModalSizeExtraLarge},
Base: newBase(TypeModal, TitleFromString("modal")),
Config: ModalConfig{
ModalSize: ModalSizeExtraLarge,
},
},
},
}
Expand Down
Expand Up @@ -4,10 +4,119 @@ <h3 class="modal-title">
</h3>
<div class="modal-body">
<app-view-container [view]="body"></app-view-container>
<form clrForm *ngIf="form" (ngSubmit)="onFormSubmit()" [formGroup]="formGroup">
<div *ngFor="let field of form.fields; trackBy: trackByFn">
<ng-container [ngSwitch]="field.type">
<ng-container *ngSwitchCase="'checkbox'">
<clr-checkbox-container>
<label [for]="field.name">{{ field.label }}</label>
<clr-checkbox-wrapper
*ngFor="let opt of fieldChoices(field); trackBy: trackByFn"
>
<input
type="checkbox"
clrCheckbox
[formControlName]="field.name"
[value]="opt.value"
[checked]="opt.checked"
/>
<label>{{ opt.label }}</label>
</clr-checkbox-wrapper>
<clr-control-error>{{ field.error }}</clr-control-error>
</clr-checkbox-container>
</ng-container>
<ng-container *ngSwitchCase="'radio'">
<clr-radio-container>
<label [for]="field.name">{{ field.label }}</label>
<clr-radio-wrapper
*ngFor="let opt of fieldChoices(field); trackBy: trackByFn"
>
<input
type="radio"
clrRadio
[formControlName]="field.name"
[value]="opt.value"
/>
<label>{{ opt.label }}</label>
</clr-radio-wrapper>
<clr-control-error>{{ field.error }}</clr-control-error>
</clr-radio-container>
</ng-container>
<ng-container *ngSwitchCase="'text'">
<clr-input-container>
<label [for]="field.name">{{ field.label }}</label>
<input
clrInput
type="text"
[name]="field.name"
[formControlName]="field.name"
[placeholder]="field.placeholder"
/>
<clr-control-error>{{ field.error }}</clr-control-error>
</clr-input-container>
</ng-container>
<ng-container *ngSwitchCase="'number'">
<clr-input-container>
<label [for]="field.name">{{ field.label }}</label>
<input clrInput type="number" [formControlName]="field.name" />
<clr-control-error>{{ field.error }}</clr-control-error>
</clr-input-container>
</ng-container>
<ng-container *ngSwitchCase="'password'">
<clr-input-container>
<label [for]="field.name">{{ field.label }}</label>
<input
clrInput
type="password"
[formControlName]="field.name"
/>
<clr-control-error>{{ field.error }}</clr-control-error>
</clr-input-container>
</ng-container>
<ng-container *ngSwitchCase="'select'">
<clr-select-container>
<label [for]="field.name">{{ field.label }}</label>
<select
clrSelect
[formControlName]="field.name"
[multiple]="field.configuration.multiple"
>
<option
*ngFor="let opt of fieldChoices(field); trackBy: trackByFn"
[value]="opt.value"
>
{{ opt.label }}
</option>
</select>
<clr-control-error>{{ field.error }}</clr-control-error>
</clr-select-container>
</ng-container>
<ng-container *ngSwitchCase="'textarea'">
<clr-textarea-container>
<label [for]="field.name">{{ field.label }}</label>
<textarea clrTextarea [formControlName]="field.name"></textarea>
<clr-control-error>{{ field.error }}</clr-control-error>
</clr-textarea-container>
</ng-container>
<ng-container *ngSwitchCase="'hidden'"> </ng-container>
<ng-container *ngSwitchDefault>
Unable to display form field type {{ field.type }}
</ng-container>
</ng-container>
<br>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" (click)="opened = false">
Close
</button>
<ng-container *ngIf="form else closeButton">
<button type="button" class="btn btn-outline" (click)="opened = false">Cancel</button>
<button type="button" class="btn btn-primary submit" (click)="onFormSubmit()">Submit</button>
</ng-container>
</div>
</clr-modal>
</clr-modal>

<ng-template #closeButton>
<button type="button" class="btn btn-primary" (click)="opened = false">
Close
</button>
</ng-template>
Expand Up @@ -5,14 +5,17 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ModalComponent } from './modal.component';
import { SharedModule } from '../../../shared.module';
import { ModalService } from '../../../services/modal/modal.service';

describe('LoadingComponent', () => {
describe('ModalComponent', () => {
let component: ModalComponent;
let fixture: ComponentFixture<ModalComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [SharedModule],
declarations: [ModalComponent],
providers: [{ provide: ModalService }],
}).compileComponents();
}));

Expand Down

0 comments on commit dc75c00

Please sign in to comment.