AngularJS Dynamically Adding Control In Repeater to Form Causes Submit - angularjs

I have a form which represents an object and an array of sub-objects contained in a repeater. I want to dynamically add sub-objects to the array. When I add a sub-object the form gets submitted unexpectedly.
See this example:
http://plnkr.co/edit/TUblgmb7N710nPL7s5tU?p=preview
My form looks like this:
<form ng-submit="handleSubmit()" ng-controller="TestController">
<div>Some Input: <input type="text"></div>
<div ng-repeat="obj in model.children">
<input type="text" ng-model="obj.text" />
</div>
<button ng-click="addChild()"> Add Child</button>
</form>
The controller looks like this...
Controllers.controller('TestController', ["$scope", function($scope) {
$scope.model = {
name: "Some Text",
children: []
};
$scope.handleSubmit = function() {
alert("Form Submitted!");
}
$scope.addChild = function() {
$scope.model.children.push({text:"Foo"});
}
}]);
Click the "Add Child" buttton. The UI is updated as expected but the form gets submitted.
I can work around this by putting the submit function in ng-click on the Save button instead of ng-submit on the form but this seems like unexpected behaviour. Can anyone explain?

The default attribute type The HTML button tag <button>My Button</button> triggers the submit event as <input type = "submit"...> does.
Now, following the idea of #GruffBunny, I have added a pInputType parameter to your method to show what button was clicked:
$scope.addChild = function(pInputType) {
$scope.model.children.push({text:"Foo", inputType : pInputType });
}
Then in the HTML block, the attribute inputTypewas added within the loop as follow:
<div ng-repeat="obj in model.children">
<hr />
<h3>{{obj.inputType}}</h3>
<div>New Input: <input type="text" ng-model="obj.text" /></div>
</div>
Finally, here are the buttons for testing the code:
<!-- With Input Type -->
<h2>Input type Button</h2>
<input type="button" ng-click="addChild('Input type Button')" value="Btn Add Child" />
<hr />
<!-- With Normal Anchor -->
<h2>HTML Anchor</h2>
Add Child Link
<hr />
<!-- Adding Bootstrap -->
<h2>HTML Bootstrap Anchor</h2>
Add Child Link
<hr />
<!-- Button Tag -->
<h2>HTML Button Tag (Triggers SUbmit Events)</h2>
<button ng-click="addChild('Triggers Submit Events')">Add Child</button>
<hr />
Here is the complete plunker: http://plnkr.co/edit/N4hSjG
For further information about this behavior, you can read this Stack Overflow question: <button> vs. <input type="button" />. Which to use?
I hope it could be useful this explanation for anyone.

Related

Pass ng-model from parent to controller

I am trying to pass ng-model located in a different HTML scope to controller when a button is clicked. It works if the button is in the same scope as the ng-model, but I want to have the button in the header.
Case 1. This works:
HTML
<header>
</header>
<content>
<label>
<input ng-model="text">
</label>
<button ng-click="save(text)">
Save
</button>
</content>
Case 2. This does not work:
HTML
<header>
<button ng-click="save(text)">
Save
</button>
</header>
<content>
<label>
<input ng-model="text">
</label>
</content>
Controller
$scope.save = function(text) {
console.log(text); // Undefined in case 2.
};
To my understanding the ng-model is better suited pointing to an object key. So I tried this:
HTML
<header>
<button ng-click="save(text)">
Save
</button>
</header>
<content>
<label>
<input ng-model="obj.text">
</label>
</content>
Controller
$scope.save = function() {
$scope.obj = {};
console.log(obj.text); // Still undefined
};
How can I pass ng-model when the button is located in the header is clicked to controller?

Can a form be invoked on a click event in AngularJS ?

I am creating a project to put into practice what I have learned about AngularJS. I created a form, which uses a controller. In the form, I have a button to save the information filled in by the user. After the information is save into the database I would like to call a second form to continue, (this form has its own controller) etc. How can I do that ?
If you're not navigating to a different view, you probably dont need another controller. You can show and hide forms conditionally with ng-if. Ie. say first form is done, you've posted it to the database. You can do something like this
$scope.form = 1
<form id="form1" ng-if="form === 1">
//your form html
</form>
<form id="form2" ng-if="form === 2">
//your form html
</form>
then when form1 is submitted, you can do
$scope.form = 2
in your controller to hide the first form and render the second one
If you're set on the different forms having different controllers, you can do something like this
<div controller="mainCtrl">
<form controller="form1Ctrl" id="form1" ng-if="form === 1">
//your form html
</form>
<form controller="form2Ctrl" id="form2" ng-if="form === 2">
//your form html
</form>
</div>
You would set the form variable from the mainCtrl's scope
You can use ng-submit for this:
<form ng-submit="goToNextForm()">
<input type="text" ng-model="email">
<button type="submit" value="submit">
</form>
And in controller:
$scope.goToNextForm = function(){
//code to save data and move to next controller/form here
}

DOM swapping in Angular JS

Basically I have two Divs in a page out of which only one will be visible at a time.
I have a text input placed inside my first div which is shown my default.
Now if the first div is hidden and the second DIV is shown,
I want to swap the text input DOM in to the second DIV. The ID of the textinput and the value it has needs to be retined on swapping.
I have a reference of the text input to be swapped in my custom directive (ref-comp in the below snippet).
How can i achieve this in angularJS ? Please help me here.
<div id="1">
<div id ="container1">
<input type="text" id="text1">
</input>
</div>
<div id ="container1">
<ref-comp id="ref1" refId ="text1">
</ref-comp>
</div>
</div>
Please have a look on it this might be help.
var app = angular.module('myApp', []);
app.controller('IndexCtrl', function($scope) {
$scope.showme = true;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div id="1" data-ng-app="myApp" data-ng-controller="IndexCtrl">
<div id ="container1" ng-show="showme">
value of text filed of div 1: {{divAVarialbe.text1}} <br>
<input type="text" id="text1" ng-model="divAVarialbe.text1">
</input>
</div>
<div id ="container1" ng-show="!showme">
value of text filed of div 2 : {{divBVarialbe.text1}} <br>
<input type="text" id="text1" ng-model="divBVarialbe.text1">
<ref-comp id="ref1" refId ="text1">
</ref-comp>
</div>
<button ng-click="showme = !showme" ng-show="!showme">Show div 1</button>
<button ng-click="showme = !showme" ng-show="showme">Show div 2</button>
</div>
You can use ng-show to swap the div and and scope variables to access the input filed of the DOM.
suppose that if use to scope variable lets say divAVarialbe and divBVariable.
then for div A divAVarialbe will be use i.e all the child model will be go inside divAVarialbe so your data str will be
divAVarialbe={"text1":"value of textfild","otherModel":"",...}
same for Div B.
In this way you can differentiate the DOM.
It base on how much you have knowledge of Object.
assume it like mvc pattern then it will be easy to code.
might be this will help.

Display value of a textbox inside another textbox using AngularJs on button click

New in AngularJs. Finding it complex a little. I have created two text box and a button. Now I want, first I will write something inside the first text box. Then I will click on the button. After that the value of the first text box will get displayed inside the second text box. I have written very little code, I didn't even mentioned the button click function as I am confused on that. Please help me to go further.
<script src="../../Scripts/angular.min.js" type="text/javascript"></script>
</head>
<body>
<div ng-app="">
<input type="text" ng-model="type">
<br />
<br />
<input type="button" value="button" onclick="myFunction()" />
<br />
<br />
<input type="text" ng-model="display" />
</div>
</body>
in your controller do ,
$scope.myFunction = function () {
$scope.display = $scope.type;
}
in your html you have to change onclick to ng-click,
<input type="button" value="button" ng-click="myFunction()" />
see this plunk for example, http://plnkr.co/edit/c5Ho1jlixwZFx7pLFm9D?p=preview
Check whether you have included angular js file in your HTML.
//add below snippet in your HTML head tag
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"> </script>

AngularJS: Required form field not woking with ng-click submit

<div ng-app>
<div ng-controller="Ctrl">
<form ng-submit="submit() ">
<textarea ng-model="text" required></textarea>
<div ng-click="submit()" style="background-color:#ff00ff;cursor:pointer;width:100px;">Create !</div>
<button type="submit" style="background-color:#ff00ff;cursor:pointer;width:100px;">Create !</button>
</form>
{{list}}
</div>
</div>
I want to submit an Angular form with a custom div button but when I do it like above, the "required" statements are not taken into account like it is done for the button.
When the textarea is empty the first button runs the submit() function anyway.
Is it possible to have the same behavior as the button ?
Here is a JsFiddle illustrating this:
http://jsfiddle.net/xKkvj/55/
I think you should be using an input rather than a div, eg:
<input type="submit" ng-click="submit()" style="background-color:#ff00ff;cursor:pointer;width:100px;">Create !</input>
I've tested it on your jsFiddle, and it works fine.
If you really must use a <div>, use it to wrap the <input>
UPDATE
It looks like you can't use anything other than an input or a button as that is what ngForm listens to for form submission. You could either extend ngForm or you could use a hidden button and trigger that from your div like so:
<div onClick="document.getElementById('hiddenButton').click();" style="background-color:#0000ff;cursor:pointer;width:100px;">Create !</div>
<button id='hiddenButton' type="submit" style="display:none;">Create !</button>
jsFiddle here. Hopefully this'll do the trick for you.
If you want to submit form from a div element, then you should manually test if form is valid in your submit handler:
function sumbit() {
if (form.$invalid) {
return;
}
// Other code...
}
The point is that when you submit your form via <input type="submit"/>, then form validation check is performed internally & form handler do not invoked in case of invalid form.
UPDATE
Your jsfiddle form handler should look like:
$scope.submit = function () {
if ($scope.submitCreateSurveyForm.$invalid) {
return;
}
if ($scope.text) {
$scope.list.push($scope.text);
$scope.text = '';
}
console.log("sent");
};

Resources