Skip to content

Commit

Permalink
mgr/dashboard: Add submit button component
Browse files Browse the repository at this point in the history
This component is to be used inside a form.

It will render a submit button with the given label.
The button will disabled itself and show a loading icon when the user clicks it,
usually initiating a request to the server, and it will stay in that state
until the request is finished.

To indicate that the request failed, returning the button to the enable state,
you need to insert an error in the form with the 'cdSubmitButton' key.

It will also check if the form is valid, when clicking the button, and will
focus on the first invalid input.

Signed-off-by: Tiago Melo <tmelo@suse.com>
  • Loading branch information
Tiago Melo committed Mar 23, 2018
1 parent 44f16c9 commit 70f8f61
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ChartsModule } from 'ng2-charts/ng2-charts';
import { AlertModule } from 'ngx-bootstrap';

import { SparklineComponent } from './sparkline/sparkline.component';
import { SubmitButtonComponent } from './submit-button/submit-button.component';
import { ViewCacheComponent } from './view-cache/view-cache.component';

@NgModule({
Expand All @@ -15,12 +16,14 @@ import { ViewCacheComponent } from './view-cache/view-cache.component';
],
declarations: [
ViewCacheComponent,
SparklineComponent
SparklineComponent,
SubmitButtonComponent
],
providers: [],
exports: [
ViewCacheComponent,
SparklineComponent
SparklineComponent,
SubmitButtonComponent
]
})
export class ComponentsModule { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<button type="submit"
class="btn btn-sm btn-primary tc_submitButton"
[disabled]="loading"
(click)="submit()">
<ng-content></ng-content>
<span *ngIf="loading">
<i class="fa fa-spinner fa-spin fa-fw"></i>
</span>
</button>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FormGroup } from '@angular/forms';

import { SubmitButtonComponent } from './submit-button.component';

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

beforeEach(
async(() => {
TestBed.configureTestingModule({
declarations: [SubmitButtonComponent]
}).compileComponents();
})
);

beforeEach(() => {
fixture = TestBed.createComponent(SubmitButtonComponent);
component = fixture.componentInstance;

component.form = new FormGroup({}, {});

fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { FormGroup } from '@angular/forms';

import * as _ from 'lodash';

/**
* This component will render a submit button with the given label.
*
* The button will disabled itself and show a loading icon when the user clicks
* it, usually initiating a request to the server, and it will stay in that
* state until the request is finished.
*
* To indicate that the request failed, returning the button to the enable
* state, you need to insert an error in the form with the 'cdSubmitButton' key.
* p.e.: this.rbdForm.setErrors({'cdSubmitButton': true});
*
* It will also check if the form is valid, when clicking the button, and will
* focus on the first invalid input.
*
* @export
* @class SubmitButtonComponent
* @implements {OnInit}
*/
@Component({
selector: 'cd-submit-button',
templateUrl: './submit-button.component.html',
styleUrls: ['./submit-button.component.scss']
})
export class SubmitButtonComponent implements OnInit {
@Input() form: FormGroup;
@Output() submitAction = new EventEmitter();

loading = false;

constructor(private elRef: ElementRef) {}

ngOnInit() {
this.form.statusChanges.subscribe(() => {
if (_.has(this.form.errors, 'cdSubmitButton')) {
this.loading = false;
_.unset(this.form.errors, 'cdSubmitButton');
this.form.updateValueAndValidity();
}
});
}

submit() {
if (this.form.invalid) {
this.focusInvalid();
return;
}

this.loading = true;
this.submitAction.emit();
}

focusInvalid() {
const target = this.elRef.nativeElement.offsetParent.querySelector(
'input.ng-invalid, select.ng-invalid'
);

if (target) {
target.focus();
}
}
}

0 comments on commit 70f8f61

Please sign in to comment.