Angularjs Form dirty not working for Dropdown - angularjs

I have a simple bootstrap form . For sake of example i have a input field and a dropdown. I want to enable the save button only when the change is made. In order to do that, i made the save button enable only if the form is dirty.
The problem is - When i change the input field it works, the button gets enabled, where as when i change the dropdown, which is basically selecting the list item, the form does not identify it as dirty and hence it is still disabled.
Any ideas?
I also tried creating an hidden input field that gets updated everytime the select value gets updated - but still it is noto working .
My sample form (pls ignore any typos since i stripped of most of the code. The functionality works just fine. it is just the disabling of button that doesnt work)
<form name="customizeForm" id="customize-form" class="bm-form" data-ng-cloak novalidate data-ng-submit="ctrl.saveCustomization(customizeForm.$valid)">
<!--if i change this input, it works -->
<input id="answer" type="text" name="answer" data-ng-model="ctrl.answer">
<!--If i change the below dropdown, it doesnt work and the button is still disabled -->
<div class="form-group dropdown col-xs-12 col-md-6" data-uib-dropdown data-keyboard-nav data-is-open="status[$index].isopen" data-ng-init="status[$index].newSelectedValue = ''">
<button id="profile-menu" type="button" class="form-control select-control dropdown-togglebtn" data-uib-dropdown-toggle>
<span class="selected" data-ng-bind-html="status[$index].newSelectedValue</span>
<span class="icon icon-down-arrow" aria-hidden="true"></span>
</button>
<ul class="dropdown-menu" role="menu" data-aria-labelledby="menu">
<li data-ng-repeat="answer in question.Answers">
{{answer.AnswerDesc}}
</li>
</ul>
</div>
<div id="save-profile" class="text-center form-submit">
<button type="submit" data-ng-disabled="!customizeForm.$dirty" id="btn-profile-questionnaire" class="btn btn-card reverse" title="Save">
Save</span>
</button>
</div>
</form>

Related

Can a mat-checkbox be used as a matStepperNext?

I want a step within a stepper to have an agreement, but don't want the extra button that says "I agree with what I just checked to agree to". Just click on the checkbox and go.
Using the standard Angular example, I swapped out the button for a checkbox and the stepper doesn't move forward.
<button mat-raised-button (click)="isLinear = !isLinear" id="toggle-linear">
{{!isLinear ? 'Enable linear mode' : 'Disable linear mode'}}
</button>
<mat-vertical-stepper [linear]="isLinear" #stepper>
<mat-step [stepControl]="firstFormGroup">
<form [formGroup]="firstFormGroup">
<ng-template matStepLabel>Agree with Terms</ng-template>
<div>
<mat-checkbox matStepperNext formControlName="firstCtrl" required> I agree </button>
</div>
</form>
</mat-step>
<mat-step [stepControl]="secondFormGroup">
<form [formGroup]="secondFormGroup">
<ng-template matStepLabel>Fill out your address</ng-template>
<mat-form-field>
<input matInput placeholder="Address" formControlName="secondCtrl" required>
</mat-form-field>
<div>
<button mat-button matStepperPrevious>Back</button>
<button mat-button matStepperNext>Next</button>
</div>
</form>
</mat-step>
<mat-step>
<ng-template matStepLabel>Done</ng-template>
You are now done.
<div>
<button mat-button matStepperPrevious>Back</button>
<button mat-button (click)="stepper.reset()">Reset</button>
</div>
</mat-step>
</mat-vertical-stepper>
Expect to click the checkbox and have the stepper move directly to step 2.
I figured it out. The key word, matStepperNext, appears to not apply to checkboxes. However, if in the checkbox HTML, where you include #stepper in your stepper's div...
<mat-vertical-stepper #stepper [linear]="isLinear">you include a (change) event calling a function...
You can add a (change) event that calls a function with that name...
<mat-checkbox matStepperNext (change)="goForward(stepper);" formControlName="firstCtrl" required> I agree </button>
Then, in the .ts, make sure to include...
import { MatStepper } from '#angular/material/stepper';
...and then add this function...
goForward(stepper: MatStepper){
stepper.next();
}
When you click the checkbox, it should progress to your next step.

Making the Bootstrap navbar searchbox work

I am trying to make a search function which works if I put in the query params into my URL directly but I don't know how to make it work so that it picks it up from the search box and executes it. I have used ng-model to map the text itself to the controller which works but the execution isn't working.
The navbar form:
<form ng-submit="doSearch()" class="navbar-form">
<div class="form-group" style="display:inline;">
<div class="col-md-offset-4 input-group" style="display:table;">
<input ng-model="search.text" class="form-control" name="search" placeholder="Search Here" autocomplete="off" autofocus="autofocus" type="text">
<span class="input-group-addon" style="width:1%;">
<span class="glyphicon glyphicon-search"></span>
</span>
</div>
</div>
By the way, my doSearch() function works just fine when I run it manually and so is the search itself. I have also validated that search.text comes through. I guess what I am asking is how do I make the icon (glyphicon-search) execute ng-submit="doSearch()" when the user clicks on it or presses enter.
Sorry if this is very obvious. I was always more on the backend side of things so am sorta new to HTML and Angular.
Thanks
You could place the icon inside a <button> element instead of <span>, tweak a bit of css to integrate it to the form field.
In regards to trigger search on enter, with jQuery something like this could be used:
$('input').keypress(function (e) {
var key = e.which;
if(key == 13) // the enter key code
{
doSearch();
}
});
did you try using <button type="submit"> before your search icon
<span class="glyphicon glyphicon-search"></span>
to specify that clicking on that button is equivalent to a submit event for that form.
So this worked in the end. First, the proper HTML which works:
<form ng-submit="doSearch()" class="navbar-form">
<div class="form-group" style="display:inline;">
<div class="col-md-offset-4 input-group" style="display:table;">
<input ng-model="search.text" class="form-control" name="search" placeholder="Search Here" autocomplete="off" autofocus="autofocus" type="text">
<span ng-click="doSearch()" class="input-group-addon" style="width:1%;">
<span class="glyphicon glyphicon-search"></span>
</span>
</div>
</div>
</form>
Furthermore, there was an issue with the view not connecting to the controller. Actually, let me rephrase that - it was connecting to the controller but only when the whole page loaded and for my test, I had a console.log('I have loaded') put in there. So when I saw "I have loaded", I thought my controller was invoked properly.
However, the doSearch() was in the controller which was connecting via angular routing, so the ng-View was not connecting to the right controller.
I am not sure if this means anything to anyone but I am writing this in case someone else comes across an issue like mine.
So just to summarise the issue was not with the HTML as I originally thought. ng-submit (for form submission when pressing enter) and ng-click (for clicking the glyphicon) does the trick.

No search on Enter key

I just built a small search app for movies using AngularJS and Elasticsearch. I used the AngularJS UI Bootstrap Typeahead for autocomplete and in testing noticed something about user interaction.
Say I want to search for actors named Tom. I type in "tom" in the search input and 5 suggestions appear - fine. However, it won't let me just search for "tom" if all I do is press Enter on the keyboard. It automatically selects the first suggestion in the dropdown. IT WILL just search for "tom" if I just click on the submit button. My form markup is below - where am I going wrong?
I want to allow my users to be able to search for the queries they enter (when they press Enter) without being limited to just the suggestions provided...
<div class="col-sm-3 col-md-6 pull-left" style="border: 1px solid red;"><form name="q" ng-submit="vm.search()" class="navbar-form" role="search">
<div class="input-group input-group-md">
<input type="text" ng-model="vm.searchTerms" class="form-control input-md" placeholder="{{ vm.searchTerms }}" name="q" typeahead-show-hint="true" uib-typeahead="query for query in vm.getSuggestions($viewValue)" typeahead-on-select="vm.search($item)">
<span class="input-group-btn">
<button class="btn btn-primary btn-md" type="submit" id="results-search-btn" ng-submit="vm.search()"><i class="fa fa-search fa-lg"></i>
</button>
</span>
</div>
It is automatically selecting the first result. So when you press enter it already has focus on that first result. You can configure the angular ui typeahead to not automatically select the first result like so:
typeahead-focus-first="false"
see their documentation for further information:
https://angular-ui.github.io/bootstrap/#/typeahead

AngularJS: First button in form fires on enter button press even though it is not a submit button

If I press the enter button after editing input_a, processInputA() is called. The submit() function is omitted.
This does not happen for input_b: It works as expected even though it is similar to input_a. The submit() function is called as expected.
How can I prevent the button after input_a from firing?
<form class="uk-form" ng-submit="submit()">
<div class="uk-form-row">
<input type="text"
name="input_a"
ng-model="buffer.inputA" ng-change="reportInputATyped()"
class="uk-width-3-10 uk-form-small">
<button ng-cloak ng-show="inputADirty" class="uk-button uk-button-small" ng-click="processInputA()">Apply</button>
/
<input type="text"
name="input_b"
ng-model="buffer.inputB" ng-change="reportInputBTyped()"
class="uk-width-6-10 uk-form-small">
<button ng-cloak ng-show="inputBDirty" class="uk-button uk-button-small" ng-click="processInputB()">Apply</button>
</div>
// ...further inputs...
</form>
AngularJS: http://angular-meteor.com
Styles: http://getuikit.com
<button> elements seem to be of default type submit if rendered through Chrome. Not what I expected intuitively.
The W4Schools.com article states the tip:
Always specify the type attribute for the element. Different browsers may use different default types for the element.
http://www.w3schools.com/tags/att_button_type.asp
Version that works if processed by Chrome:
<form class="uk-form" ng-submit="submit()">
<div class="uk-form-row">
<input type="text"
name="input_a"
ng-model="buffer.inputA" ng-change="reportInputATyped()"
class="uk-width-3-10 uk-form-small">
<button type="button" ng-cloak ng-show="inputADirty" class="uk-button uk-button-small" ng-click="processInputA()">Apply</button>
/
<input type="text"
name="input_b"
ng-model="buffer.inputB" ng-change="reportInputBTyped()"
class="uk-width-6-10 uk-form-small">
<button type="button" ng-cloak ng-show="inputBDirty" class="uk-button uk-button-small" ng-click="processInputB()">Apply</button>
</div>
// ...further inputs...
</form>

Angular UI-Bootstrap dropdown button on ng-options

<select class="form-control" data-ng-options="t.name for t in vm.types"
data-ng-model="vm.object.type"></select>
The code above obviously displays a basic dropdown in a standard form-control manner. I've been trying to figure out how to convert this to a button style dropdown using Angular's ui-bootstrap directives but can't seem to get anywhere. Has anyone tried this?
I hope you already found the answer, but maybe someone else will find this useful. The previous answer refers to a common drop down not a button drop down. Here is an example, but without the benefits of hg-option while I didn't use a select but a button.
<div class="input-group">
<div class="input-group-btn" ng-class='{open: open}'>
<button class="btn dropdown-toggle"
data-toggle="dropdown"
ng-click='open=!open'>
Action<span class="caret"></span></button>
<ul class="dropdown-menu">
<li ng-repeat="choice in choices"
ng-click="setChoiceIndex($index);$parent.open =!$parent.open">
{{choice}}</li>
</ul>
</div>
<input type="text" ng-model="choices[index]" class="form-control">
</div>
where choices is an array of strings that will be displayed in the drop down and index is another variable in the controller scope that will reflect the selected choice.
I have created a basic demo of a drop down using angular bootstrap..
Visit :http://plnkr.co/edit/Mfw5zABqPTgLL4DAgAA3?p=preview
Hope this is what your are looking for.

Resources