5

I have an unusual problem. My form loos like this:

     <form>
        <button ng-class="{'btn-primary': ts.test.current == true}"
                ng-click="$state.transitionTo('s.e.q');"
                ng-show="ts.test.current && ts.test.userTestId">
            View
        </button>
        <button ng-class="{'btn-primary': ts.test.current == true}"
                ng-click="getTest(ts.test)"
                ng-show="ts.test.current && !ts.test.userTestId">
            Acquire
        </button>
     </form>

What I need is for the enter key to trigger the action of the current button primary. Note that the button primary can be one of two buttons depending on the state of other items on the page.

Can anyone suggest how this could be done? I saw reference to the ng-enter directive but if possible I think it would be better for me not to use non-standard directives.

Here is what I have tried so far. Unfortunately when I click enter nothing happens:

            <form ng-show="ts.test.current && ts.test.userTestId"
                  ng-submit="$state.transitionTo('s.e.q');">
                <button ng-class="{'btn-primary': ts.test.current == true}"
                        type="submit">
                    View
                </button>
            </form>
            <form ng-show="ts.test.current && !ts.test.userTestId"
                  ng-submit="getTest(ts.test)">
                <button class="btn"
                        ng-class="{'btn-primary': ts.test.current == true}"
                        type="submit">
                    Acquire
                </button>
            </form>
Vishwanath
  • 6,284
  • 4
  • 38
  • 57
Alan2
  • 23,493
  • 79
  • 256
  • 450
  • You need to have focus on an element in a form for pushing ENTER to cause a form to submit. As your form has no element other than the button could you explain in what state your expecting the form to be in when the user pushes enter? – Sam Mar 06 '15 at 06:59

4 Answers4

5

From the docs

You can use one of the following two ways to specify what javascript method should be called when a form is submitted:

ngSubmit directive on the form element ngClick directive on the first button or input field of type submit (input[type=submit]) To prevent double execution of the handler, use only one of the ngSubmit or ngClick directives. This is because of the following form submission rules in the HTML specification:

If a form has only one input field then hitting enter in this field triggers form submit (ngSubmit) if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter doesn't trigger submit if a form has one or more input fields and one or more buttons or input[type=submit] then hitting enter in any of the input fields will trigger the click handler on the first button or input[type=submit] (ngClick) and a submit handler on the enclosing form (ngSubmit)

So the trick becomes having only one button of type "submit" in your form at any given time, and choosing that button based on the state of your model. With multiple buttons, enter will trigger the ng-click on the the first button with type="submit" (and it will call ng-submit, although that's not needed here)

Unfortunatly, you can't modify the "type" of a button with a binding like this:

<button type="{{isPrimary ? 'submit' : 'button'}}">Acquire</button>

Also, ng-show doesn't remove the button from the DOM, so your current solution leaves you with multiple buttons of type="submit", in which case only the first one (hidden or not) will have it's click function executed.

If you only wanted to have one button visible at any given time, then changing ng-show to ng-if will do the trick (see this Plunk).

If you want both buttons visible, then the only solution I can come up with that doesn't involve creating a custom button directive is to duplicate your button blocks so that you use a different block based on your condition (see this Plunk).

<form>
    <div ng-if="ts.test.userTestId">
        <button ng-class="{'btn-primary': ts.test.current == true}"
            ng-click="$state.transitionTo('s.e.q');"
            type="submit">
            View
        </button>
        <button ng-class="{'btn-primary': ts.test.current == true}"
            ng-click="getTest(ts.test)"
            type="button">
            Acquire
        </button>
    </div>
    <div ng-if="!ts.test.userTestId">
        <button ng-class="{'btn-primary': ts.test.current == true}"
            ng-click="$state.transitionTo('s.e.q');"
            type="button">
            View
        </button>
        <button ng-class="{'btn-primary': ts.test.current == true}"
            ng-click="getTest(ts.test)"
            type="submit">
            Acquire
        </button>
    </div>

 </form>
Joe Enzminger
  • 11,110
  • 3
  • 50
  • 75
2

Change the button which should not submit the form to <button type="button">

button  "clickable, but without any event handler until one is assigned"

See also: AngularJS: All buttons inside form triggers submit?

Community
  • 1
  • 1
jantimon
  • 36,840
  • 23
  • 122
  • 185
  • Can you explain a bit more or add an example based on my code. What I need to do is to have the Enter key do the same actions as in the click events. For example: ng-click="$state.transitionTo('s.e.q');" or ng-click="getTest(ts.test)" depending on which button is showing. Thanks – Alan2 Feb 28 '15 at 12:30
  • You should listen for the ng-submit of the form instead of the click. – jantimon Feb 28 '15 at 12:32
  • I tried this and have put my code in the question. But when i click enter nothing happens even though clicking the button works. – Alan2 Feb 28 '15 at 15:53
1

Do try ng-if instead of ng-show

CODE

<form>
    <button ng-class="{'btn-primary': ts.test.current == true}"
            ng-click="$state.transitionTo('s.e.q');"
            ng-if="ts.test.current && ts.test.userTestId">
        View
    </button>
    <button ng-class="{'btn-primary': ts.test.current == true}"
            ng-click="getTest(ts.test)"
            ng-if="ts.test.current && !ts.test.userTestId">
        Acquire
    </button>
 </form>
Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
Vinay K
  • 5,562
  • 1
  • 18
  • 27
0

You need to provide a submit method on the form itself and then just mark buttons as type="submit" if you want them to submit the form.

See Angular documentation on ngSumbit.

Reading your code it looks as though you only want one button visible at any given time. Based on that, I think what you really want is modify the label on the button depending on the condition of ts.test.userTestId.

Here's a jsfiddle demonstrating 1) the form submit handling, 2) the label change on your View/Acquire button, and 3) the fact that you can have an extra button if you really want it.

function ButtonController($scope) {
    $scope.ts = {
        test: {
            userTestId: ''
        }
    }
    $scope.getTest = function (value) {
        alert('getTest called');
    }
    $scope.submit = function () {
        if ($scope.ts.test.userTestId) {
            alert("call $state.tranistionTo('s.e.q')");
        } else {
            $scope.getTest($scope.ts.test);
        }
    }
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
    <h2>The button</h2>
    <div ng-controller="ButtonController">
        <form ng-submit="submit()">
            <input type="text"
                   ng-model="ts.test.userTestId">
            <button type="submit">{{ ts.test.userTestId ? 'View' : 'Acquire' }}</button>
          
            <br><br>
            Here's an extra button which also submits the form. Notice that the submit routine
            still only runs once and having this extra button doesn't cause any problems.
            <br>
            <button type="submit">Some other submit button</button>

        </form>
    </div>
</div>
ptevans
  • 516
  • 5
  • 9