Autogrowing Inputs

$scope.autogrowCurrencyValue = 1111; $scope.autogrowCurrencyPencilValue = 567; $scope.autogrowNumberValue = 30; $scope.autogrowTextValue = 'Leeroy Jenkins';
<!-- Autogrow currency input --> <input ws-currency="{autogrow: true, integer:true}" ng-model="autogrowCurrencyValue"> <!-- With currency symbol --> <input ws-currency="{autogrow: true, integer:true, symbol:'£' }" ng-model="autogrowCurrencyValue"> <!-- With currency code --> <input ws-currency="{autogrow: true, integer:true, currencyIsoCode:'EUR' }" ng-model="autogrowCurrencyValue"> <!-- Autogrow currency input with pencil icon --> <input ws-currency="{autogrow: true, integer:true}" show-pencil ng-model="autogrowCurrencyPencilValue"> <!-- Autogrow number input --> <input autogrow-input type="number" ng-model="autogrowNumberValue"> <!-- Autogrow text input --> <input autogrow-input show-pencil type="text" ng-model="autogrowTextValue" ng-trim="false">
            $scope.autogrowCurrencyValue = {{autogrowCurrencyValue}};
            $scope.autogrowCurrencyPencilValue = {{autogrowCurrencyPencilValue}};
            $scope.autogrowNumberValue = {{autogrowNumberValue}};
            $scope.autogrowTextValue = {{autogrowTextValue}};
          
Autogrow currency input
expected income
Autogrow currency input (with currency symbol)
Autogrow currency input (with currency ISO code)
Autogrow currency input (with pencil icon)
Expected cost:
Autogrow number input
years old
Autogrow text input
My name is

Currency Input

$scope.currencyValue1 = 111; $scope.currencyValue2 = 222; $scope.currencyValue3 = 333; $scope.currencyValue4 = 444; $scope.currencyValue5 = 555; $scope.currencyValue6 = 666;
<!-- Default currency input no value --> <input ws-currency> <!-- Default currency input with cents --> <input ws-currency ng-model="currencyValue1"> <!-- Default currency input integers only (no cents) --> <input ws-currency="{integer:true}" ng-model="currencyValue2"> <!-- Currency input with onChange event --> <input ws-currency ng-model="currencyValue3" ng-change="log('change');"> <!-- Currency input with ngFocus event --> <input ws-currency ng-model="currencyValue3" ng-focus="log('currency focused')"> <!-- Currency input with ngBlur event --> <input ws-currency ng-model="currencyValue3" ng-blur="log('currency blurred')"> <!-- Currency input with clearOnInitialFocus set to true --> <input ws-currency="{clearOnInitialFocus: true}" ng-model="currencyValue3"> <!-- Currency input with custom validation odd digits only --> <div ng-class="{ 'has-error' : (testFormCents.fourCharCurrency.$touched && testFormCents.fourCharCurrency.$invalid) }"> <form name="testFormCents" method="post" novalidate> <input ws-currency name="fourCharCurrency" ng-pattern="/^[.13579]*$/" ng-model="currencyValue4"> </form> </div> <!-- Currency input with custom validation Max 4 Chars (no cents) --> <div ng-class="{ 'has-error' : (testFormNoCents.fourCharCurrency.$touched && testFormNoCents.fourCharCurrency.$invalid) }"> <form name="testFormNoCents" method="post" novalidate> <input ws-currency integer="true" name="fourCharCurrency" maxlength="4" ng-model="currencyValue5"> </form> </div> <!-- Currency input with min and max (between 1 and 1000) --> <input ws-currency="{min: 1, max: 1000}" integer="true" name="minMax" ng-model="currencyValue6">
            $scope.currencyValue1 = {{currencyValue1}};
            $scope.currencyValue2 = {{currencyValue2}};
            $scope.currencyValue3 = {{currencyValue3}};
            $scope.currencyValue4 = {{currencyValue4}};
            $scope.currencyValue5 = {{currencyValue5}};
            $scope.currencyValue6 = {{currencyValue6}};
          
Default currency input no value Default currency input with cents Default currency input integers only (no cents) Disabled default currency input integers only (no cents) Currency input with ng-change event Currency input with ngFocus event Currency input with ngBlur event Currency input with clearOnInitialFocus set to true Currency input with custom validation odd digits only
Currency input with custom validation Max 4 Chars (no-cents)
Currency input with min and max (between 1 and 1000)

Footer

$scope.defaultLanguage = 'fr_CA'; $scope.availableLanguages = ['en_CA', 'fr_CA', 'ru_RU'].join(',');
<ws-footer lang="myLang" langs="availableLanguages"></ws-footer>

Content Selector

$scope.contentOptions = [ {body: "test1", header: "head1", value: "a"}, {body: "test2", header: "head2", value: "b", disabled: true}, {body: "test3", header: "head3", value: "c", color: "#7cb7b6"}, {body: "test4", header: "head4", value: "d", color: "#f27c5e"}, {body: "test5", header: "head5", value: "e"}, {body: "test6 <br/><br/><a href="http://www.wealthsimple.com" target="_blank">Wealthsimple</a>", header: "head6", value: "f"} ]; $scope.multiContentOptions = angular.copy($scope.contentOptions); $scope.stackedContentOptions = [ {header: "head1", value: "a"}, {header: "head2", value: "b"}, {header: "head3", value: "c"}, {header: "head4", value: "d"} ]; $scope.selectedOption = $scope.contentOptions[0]; $scope.selectedOptions = [$scope.multiContentOptions[1], $scope.multiContentOptions[4]]; $scope.selectedStackedOption = $scope.stackedContentOptions[0];
<!-- Single select --> <ws-content-selector options="contentOptions" selected="selectedOption" type="single" row-size="4"/> Selected Value: {{ selectedOption.value }} <!-- Multi select --> <ws-content-selector options="contentOptions" selected="selectedOption" type="multi" row-size="4"/> Selected Value: {{ selectedOption.value }} <!-- Single select - smaller row size --> <ws-content-selector options="contentOptions" selected="selectedOption" type="single" row-size="2"/> Selected Value: {{ selectedOption.value }} <!-- Stacked select --> <ws-content-selector options="stackedContentOptions" selected="selectedStackedOption" type="single" stacked="true"/> Selected Value: {{ selectedStackedOption.value }} <ws-content-selector options="stackedContentOptions" selected="selectedStackedOption" type="single" stacked="true" expandable="true" /> <!-- With form validations --> <ng-form name="contentSelectorForm"> <ws-content-selector name="contentSelector" options="stackedContentOptions" ng-model="selectedModel" type="multi" stacked="true" required ng-change="log('Something changed!')"/> </ng-form> <div ng-style="{ 'color': contentSelectorForm.contentSelector.$valid ? 'green' : 'red' }">Is valid?: {{ contentSelectorForm.contentSelector.$valid }}</div>
Single select
Selected Value: {{ selectedOption.value }}
Multi select
Selected Values:
Single select - smaller row size
Selected Value: {{ selectedOption.value }}
Stacked select
Selected Value: {{ selectedStackedOption.value }}
Stacked select expandable
Selected Value: {{ selectedStackedOptionExpandable.value }}
Stacked select neutral
Selected Value: {{ selectedStackedContentOptionsNeutral.value }}
Selected Values:
Is valid?: {{ contentSelectorForm.contentSelector.$valid }}

Notification

Try pairing with ngSticky to give your notifications some staying power.

<ws-notification type="danger" dismissible="false" actionable="false" body-string="Something bad happened :("></ws-notification> <ws-notification type="success" dismissible="false" actionable="false" body-string="Something good happened :)"></ws-notification> <ws-notification type="info" dismissible="false" actionable="false" body-string="Something informative happened :|"></ws-notification> <ws-notification type="neutral" dismissible="true" dismiss="yell('You dismissed me, how could you :(')" actionable="false" body-string="Something neautral happened and you can dismiss it :\"></ws-notification> <ws-notification timeout="5000" type="success" dismissible="false" actionable="false" body-string="I will disapear in a few seconds much like your fading youth."></ws-notification> <ws-notification type="danger" dismissible="false" actionable="false" header-string="Something happened" body-string="... and it must be important, look ^ it even has a header \ (•◡•) /"></ws-notification> <ws-notification type="neutral" dismissible="true" actionable="true" header-string="Whoa!" body-string="... something happened and you can do a thing. I wonder what it does ⚆ _ ⚆ " action-string="Press it" action="yell('👏 Bravo, want a 🍪?')"></ws-notification>

Fancy Percent

<ws-fancy-percent number="4"></ws-fancy-percent> <ws-fancy-percent number="null" color="true"></ws-fancy-percent> <ws-fancy-percent number="-3.1415" to-fixed="2" color="true"></ws-fancy-percent> <ws-fancy-percent number="3.10" to-fixed="2"></ws-fancy-percent> <ws-fancy-percent number="3.1415" to-fixed="0" color="true"></ws-fancy-percent>

Fancy Currency

<ws-fancy-currency number="4567"></ws-fancy-currency> <ws-fancy-currency number="null" color="true"></ws-fancy-currency> <ws-fancy-currency number="-4567.890123" to-fixed="2" color="true"></ws-fancy-currency> <ws-fancy-currency number="4567.80" to-fixed="2"></ws-fancy-currency> <ws-fancy-currency number="4567.890123" to-fixed="0" symbol="¥" color="true"></ws-fancy-currency> <ws-fancy-currency number="4567.890123" to-fixed="0" symbol="¥" color="true"></ws-fancy-currency> <ws-fancy-currency number="4567.80" to-fixed="0" symbol="€" symbol-end="true"></ws-fancy-currency> <ws-fancy-currency number="4567.80" to-fixed="0" currency-iso-code="EUR"></ws-fancy-currency>

Progress checkmark

<ws-progress-checkmark class="responsive-progress-checkmark" bgcolor="#c6e1e1" color="75b1b0" completed-steps="1" total-steps="4" rounded="false" radius="20" stroke="7" responsive="true"></ws-progress-checkmark> <ws-progress-checkmark color="#999999" completed-steps="1" total-steps="4"></ws-progress-checkmark> <ws-progress-checkmark completed-steps="4" total-steps="4"></ws-progress-checkmark>

Two-part allocation bar

<ws-two-part-allocation-bar text-left="60%" text-right="40%" width-percent="60"></ws-two-part-allocation-bar> <ws-two-part-allocation-bar title-left="Equity" title-right="Fixed income" text-left="$2,000" text-right="$8,000" width-percent="20"></ws-two-part-allocation-bar>

Chunk Filter

{{['a', 'b', 'c', 'd'] | chunk : 2}} {{['a', 'b', 'c', 'd'] | chunk : 3}}
{{['a', 'b', 'c', 'd'] | chunk : 2}}
{{['a', 'b', 'c', 'd'] | chunk : 3}}

Title Case

{{'hello world' | titleCase}} {{'HELLO WORLD' | titleCase}}
{{'hello world' | titleCase}}
{{'HELLO WORLD' | titleCase}}

Remove Salutation

{{'Sir Schmoopy of Awesometon' | removeSalutation}} {{'Dr. Sigmund Freud' | removeSalutation}} {{'Steve Smith' | removeSalutation}}
{{'Sir Schmoopy of Awesometon' | removeSalutation}}
{{'Dr. Sigmund Freud' | removeSalutation}}
{{'Steve Smith' | removeSalutation}}

Secondary Navigation

$scope.secondaryNavOptions = [ { text: "Option 1", state: "nav-state-one", }, { text: "Option 2", state: "nav-state-two", }, { text: "Option 3", state: "nav-state-three", } ]; $scope.secondaryNavOptionsTranslations = [ { stringId: "nav.options.one", state: "nav-state-one", }, { stringId: "nav.options.two", state: "nav-state-two", }, { stringId: "nav.options.three", state: "nav-state-three", } ];
<ws-secondary-nav options="secondaryNavOptions"></ws-secondary-nav> <ws-secondary-nav options="secondaryNavOptionsTranslations"></ws-secondary-nav>

Declarative Modal

$scope.somePromiseReturingFunction = () => { return $timeout(() => { console.log('called after action button is clicked'); }, 1000); }; $scope.someOtherPromiseReturingFunction = () => { return $timeout(() => { console.log('called after dismiss button is clicked'); }, 1000); };
<ws-modal on-action="somePromiseReturingFunction()" on-cancel="someOtherPromiseReturingFunction()"> <ws-modal-trigger> Click me to open a modal. </ws-modal-trigger> <ws-modal-body> Whatever HTML you want in here, including other directives. </ws-modal-body> </ws-modal> <ws-modal on-action="somePromiseReturingFunction()" on-cancel="someOtherPromiseReturingFunction()" trigger-id="fancy-modal"> <ws-modal-trigger> Click me to open a <b><i><u>FANCY</u></i></b> modal. </ws-modal-trigger> <ws-modal-body> <p><b>Whatever</b> HTML you want in here, <i><u>including other directives</i></u>.</p> </ws-modal-body> <ws-modal-action> <h2>Make it so, #1.</h2> </ws-modal-action> <ws-modal-dismiss> <smaller>Actually, nope.</smaller> </ws-modal-dismiss> <ws-modal-progress> Just you wait! </ws-modal-progress> </ws-modal> <a ng-click="wsModalTriggerService.openModal('fancy-modal')"> Open modal from external trigger </a>
Click me to open a modal. Whatever HTML you want in here, including other directives. Click me to open a FANCY modal.

Whatever HTML you want in here, including other directives.

Make it so, #1.

Actually, nope. Just you wait!
Open modal from external trigger

Modal (deprecated)

If you can, use the declarative modal instead. It avoids the need for `bind-html` and results in cleaner code in many cases.

$scope.openModal = () => { wsModalService.open({ bodyString: 'Some <b>text</b> to put inside of the modal body.', actionString: 'Confirm this action', actionInProgressString: 'Confirming...', dismissString: 'Cancel', action: (cb) => { // You may have an asynchronous AJAX call here. We'll simulate // that with a timeout. setTimeout(() => { console.log('called after Confirm button is clicked'); cb(); }, 1000); }, dismiss: () => { console.log('called after Cancel link is clicked'); }, }); };
<button ng-click="openModal()" class="button primary-action">Open modal</button>

Expander

$scope.expanderExpanded = function (instanceId) { console.log('OHAI', instanceId); } $scope.expanderCollapsed = function (instanceId) { console.log('KTHXBAI', instanceId); }
<ws-expander show-text="Show details" hide-text="Hide details" on-expand="expanderExpanded('expanderInstance1')" on-collapse="expanderCollapsed('expanderInstance1')"> <ws-expander-header> <h5>Whatever you want in the header.</h5> </ws-expander-header> <ws-expander-body> <p>Whatever you want in the body</p> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur feugiat lacinia orci faucibus dignissim. Donec pharetra, ipsum a aliquam pharetra, felis libero ornare nunc, et egestas nisi nisi ac metus. </p> </ws-expander-body> </ws-expander> <div style="width: 300px"> <ws-expander show-text="Reveal further considerations" hide-text="Obscure extraneous minutiae" toggle-width-percent="80"> <ws-expander-header> <h5>Yo</h5> </ws-expander-header> <ws-expander-body> <p>OHAI</p> </ws-expander-body> </ws-expander> </div>
Whatever you want in the header.

Whatever you want in the body

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur feugiat lacinia orci faucibus dignissim. Donec pharetra, ipsum a aliquam pharetra, felis libero ornare nunc, et egestas nisi nisi ac metus.

Yo

OHAI

Signature Pad

$scope.saveSignature = function(data) { console.log('What a fine looking signature you have!'); $scope.signatureData = data; } $scope.redoSignature = function() { $scope.signatureData = null; }
<ws-signature-pad on-save="saveSignature(signatureData)" on-redo="redoSignature"></ws-signature-pad>

Card Loading Indicator

const vm = this; vm.$onChanges = (changes) => { if (changes.ready) { _setShow(changes.ready.currentValue); } }; function _setShow(ready) { vm.show = false; $timeout(() => { vm.show = ready; }, vm.delay); }
<ws-card-loading-indicator ready="cardReadiness" error-message="Failed to load." min-height="150px"> <h3 class="card-loading-indicator-example-content">Hello, world!</h3> </ws-card-loading-indicator> <div class="row-lg"> <div class="col-6"> <ws-card-loading-indicator ready="cardReadiness" error-message="Load failed." min-height="100px" delay="1300" no-card-background="true"> <h3 class="card-loading-indicator-example-content">Hello, world 2!</h3> </ws-card-loading-indicator> </div> </div>
ready is: {{cardReadiness}}

Hello, world!

Hello, world 2!

Carousel

$scope.slideActivated = function (slideIndex) { console.log('OHAI slide', slideIndex); }
<ws-carousel on-slide-activated="slideActivated(slideIndex)"> <ws-carousel-slide> <div class="carousel-slide" style="height: 600px"> <button ng-click="slideActivated('0 - tall')">0 - tall</button> </div> </ws-carousel-slide> <ws-carousel-slide ng-repeat="i in [1, 2, 3, 4, 5, 6, 7, 8]"> <div class="carousel-slide"> <button ng-click="slideActivated(i)">{{ i }}</button> </div> </ws-carousel-slide> </ws-carousel>

Date Picker

$scope.changingDate = new Date('Tue Jan 25 2017 00:00:00 GMT-0400 (EDT)'); let currentDateIsDefault = true; $scope.changeDate = function() { if (currentDateIsDefault) { $scope.changingDate = new Date('Tue Jan 25 2017 00:00:00 GMT-0400 (EDT)'); } else { $scope.changingDate = new Date('Tue Dec 24 2017 00:00:00 GMT-0400 (EDT)'); } currentDateIsDefault = !currentDateIsDefault; }
Default settings <ws-date-picker> </ws-date-picker> Default date, min and max dates, disabled dates <ws-date-picker default-date="'2017-01-04'" min-date="2017-01-01" max-date="2017-01-25" disabled-dates="['2017-01-05', '2017-01-20']" disable-weekends="true"> </ws-date-picker> Date format, min and max years <ws-date-picker format="'yyyy-MM-dd'" min-year="2016" max-year="2017" disabled-dates="['Feb 1, 2017', 'Feb 7, 2017', '2017/02/08']" default-date="'Feb 10, 2017'"> </ws-date-picker> Disable business days, first day of week <ws-date-picker format="'d, M, yy'" disable-next-n-business-days="7" first-day-of-week="monday"> </ws-date-picker> Editable input <ws-date-picker editable="true"> </ws-date-picker> <div>Setting data with ngModel</div> <button ng-click="changeDate()" class="button primary-action">Change date</button> <ws-date-picker ng-model="changingDate" min-date="2017-01-01"> </ws-date-picker>
Default settings Default date, min and max dates, disabled dates Date format, min and max years Disable business days, first day of week Editable input
Setting data with ngModel

Multiple Inputs

$scope.multipleInputCompleted = function (result) { console.log('Multiple inputs form completed with ' + result); } $scope.multipleInputReadonly = false;
<ws-multiple-input number-of-inputs="3" on-completed="multipleInputCompleted(result)" is-readonly="multipleInputReadonly"></ws-multiple-input> <ws-multiple-input number-of-inputs="6" on-completed="multipleInputCompleted(result)" is-readonly="multipleInputReadonly" auto-focus="true"></ws-multiple-input> <ws-multiple-input number-of-inputs="6" on-completed="multipleInputCompleted(result)" is-readonly="multipleInputReadonly" force-single-input="true" value="'123456'"></ws-multiple-input>

Validation Messages

<div ng-form="validationMessagesExampleForm"> <input class="form-input-text" placeholder="Example email field" type="email" name="exampleEmail" ng-model="validationMessagesExampleModel.exampleEmail" required> <ws-validation-messages errors="validationMessagesExampleModel" model="validationMessagesExampleModel" attribute="exampleEmail" form-name="validationMessagesExampleForm.exampleEmail"> </ws-validation-messages> </div>

Stepper

$scope.steps = [ { id: 1, title: 'Conservative' }, { id: 2, title: 'Moderate' }, { id: 3, title: 'Growth' }, { id: 4, title: 'Aggressive' } ]; $scope.activeStepId = 3;
<ws-stepper steps="steps" active-step="activeStepId"></ws-stepper>

Dropdown Select

$scope.wsDropdownSelectLabel = 'Choose an item'; $scope.wsDropdownSelectItems = [ { id: 'item1', label: 'Item 1', selected: false }, { id: 'item2', label: 'Item 2', selected: false }, { id: 'item3', label: 'Item 3', selected: false }, ]; $scope.onWsDropdownSelectItemSelection = (selectedItem) => { $scope.wsDropdownSelectLabel = selectedItem.label; $scope.wsDropdownSelectItems = $scope.wsDropdownSelectItems.map(currentItem => ({ ...currentItem, selected: currentItem.id === selectedItem.id, })); };
<ws-dropdown-select items="wsDropdownSelectItems" label="wsDropdownSelectLabel" on-item-selection="onWsDropdownSelectItemSelection(item)" ></ws-dropdown-select>

Input Pills

$scope.onWsInputPillsChange = function (pills, pillInput) { console.log('WsInputPills output', pills.concat([pillInput])); };
<ws-input-pills placeholder-text="Type something here..." on-model-change="onWsInputPillsChange(pills, pillInput)" ></ws-input-pills>

Contenteditable Shim

$scope.foo = 'I am an editable paragraph.'; $scope.onFooChanged = function (newFoo) { console.log('Editable foo has changed to', newFoo); };
<p contenteditable="true" ws-contenteditable ng-model="foo" ng-change="onFooChanged(foo)"/> <p> Echo: {{ foo }} </p>