Angular - Controller can't see my variables in html - html

I'm here because i am not being able to make my controller see my html variables our functions, maybe you guys see something i dont =(
HTML:
<article ng-controller="CreateUserController">
<div class="well">
<center>
<h1>Registrar</h1> <button ng-click="test()">Teste</button>
</br>
<form name="form">
<div class="form-group has-feedback"
ng-class="{
'has-error': form.name.$invalid && form.name.$dirty,
'has-success': form.name.$valid && form.name.$touched
}">
<div>
<input ng-disabled="true" type="name" required name="name" class="form-control" placeholder="Nome" ng-model="user.name">
<p class="help-block" ng-messages="form.name.$error">
<span ng-message="required">Nome esta vazio.</span>
</p>
</div>
</div>
</form>
</center>
</div>
</article>
JS:
angular.module('auth').controller('CreateUserController', [
'$scope', '$http', '$location','$state','$routeParams', '$modal','$rootScope',"$resource","Auth",'UserCompaniesService',
function($scope, $http, $location,$state,$routeParams, $modal,$rootScope,$resource,Auth,UserCompaniesService){
$scope.signedIn = Auth.isAuthenticated;
$scope.logout = Auth.logout;
var Account = $resource('/accounts/'+$routeParams.id+'.json',
{},
{ "show": { "method": "GET" }});
account = Account.get({"account_id":$routeParams.id});
//Not being seen
$scope.test = function() {
alert('teste');
}
$scope.user.name = account.name;//$scope.user is not being seen
$scope.user.email = account.email;
user.html.erb
<article ng-app="auth">
<div ng-view></div>
</article>
Can you guys please help me?

It looks like you want to have an object called user on the $scope:
$scope.user.
You have values tied to this object in the model. You have to create this object yourself in your controller's constructor:
$scope.user = {};
Then your model bindings will populate things like
$scope.user.name on it from the input in the HTML.

Related

ng-switch not passing argument

I'm using ng-switch to switch between two functionalities on my webapp, downloading and uploading (controlled by two buttons). When the user wants to download, I use a textbox and submit button to pass the search query to an $http POST request in my js file.
This is the HTML code:
<button class="btn" name="search" ng-click="name = 'download'">Search & Download</button>
<button class="btn" name="upload" ng-click="name = 'upload'">Upload & Index</button>
<div ng-switch="name">
<div ng-switch-when="download">
<input type="text" ng-model="docsterm" my-enter="postData()" placeholder="Search">
<br><br>
<uib-accordion close-others="oneAtATime">
<div uib-accordion-group class="panel-default" heading={{result._source.filename}} ng-repeat="result in results.data.hits.hits">
<span ng-bind-html="highlight(result._source.attachment.content, docsterm)"></span>
<br><br>
<button class="btn">Preview</button>
<!-- Create the download button -->
<button class="btn" ng-click="download(result._source.data, result._source.filename, result._source.attachment.content_type)"><i class="fa fa-download"></i>
<!-- <textarea id="textbox">Type something here</textarea> <button id="create">Create file</button> <a download="info.txt" id="downloadlink" style="display: none">Download</a> -->
<br>
<!--
<ul uib-pagination boundary-links="true" total-items="results['hits']['total']" ng-model="currentPage" items-per-page="5" class="pagination-sm" previous-text="‹" next-text="›" first-text="«" last-text="»"></ul>
-->
</div>
</uib-accordion>
</div>
<div ng-switch-when="upload">
<!-- Multiple files -->
<button class="btn" ngf-select ng-model="files" ngf-multiple="true">Select Files</button>
<button class="btn" ng-click="submit()">Submit</button>
</div>
</div>
This is my js code:
docsApp.controller('docsController', function ($scope, $http, $sce) {
$scope.docsterm = "";
$scope.results = "";
$scope.currentPage = 1;
$scope.content = "";
$scope.content_type = "";
$scope.postData = function(docsterm) {
$http({
url: 'http://192.168.100.30:9200/my_index4/_search?q=' + $scope.docsterm,
method: "POST"
})
.then(function(response) {
$scope.results = response;
// $scope.content_type = response.data.
console.log($scope.results);
/*console.log($scope.content);
console.log($scope.content_type);*/
},
function(response) { // optional
$scope.results = "No results found."
});
}
However, docsterm is not being passed through to the js file.
In the console, I can see the $http request being sent is:
http://192.168.100.30:9200/my_index4/_search?q=
It should be:
http://192.168.100.30:9200/my_index4/_search?q=whateverDocstermIs
Of note, the exact download function code works fine when it is not nested inside the ng-switch, which leads me to believe that ng-switch is causing some issues.
Any ideas? Thanks!
My guess, it's because ng-switch behaves like ng-if - it creates its own scope.
To reach the scope of the controller you need to have $parent. before the model
<input type="text" ng-model="$parent.docsterm" my-enter="postData()" placeholder="Search">
Here is an example of this (with and without $parent)
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.name = "download"
$scope.foo = function() {
console.log("Works:", $scope.docsterm);
console.log("Doesn't work:", $scope.docsterm2);
}
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-switch="name">
<div ng-switch-when="download">
<input type="text" ng-model="$parent.docsterm">
<input type="text" ng-model="docsterm2">
<button ng-click="foo()">Click</button>
</div>
<div ng-switch-when="upload">
...
</div>
</div>
</div>
</body>
</html>

Fullcalendar on Symfony add/modify events through modal and send back Json file to Database

I am working on a project with Symfony 2.8. My main goal is to create a dynamic calendar based on Fullcalendar library.
I add my events called "dispos" (avalabilities in English) and "Rdvs" (appointments" in English) through a Json request and ajax. This works fine.
Now, I would like to transform availabilites into appointements (which are both considered as events in Fullcalendar).
E.g : When someone clicks on one availability a modal shows up, then the person fills the form in it and clicks "save" button.
When the "save" button is clicked, all informations entered in the form are sent and saved (through a Json request) into my Database and the appointment is taken
--> all events of the current should be reloaded through ajax, the event should be displayed with the title of the event entered (name of the patient) and the modal should contain all informations given/wrote before "save" action.
I tried to do it but my ajax is not working since events do not reload after saving everything else is working.
Anyway, I think I did it wrong somewhere. The code I will show you in my Controller returns a view because I didn't manage to return a response (+ I think routing or something is bad but don't know how to fix it...)
Any clue or advice woud be really appreciated :)
So here is my code :
TakeRdvAction in my controller :
/* ----------------- /
/ --- TAKE RDV ---- /
/ ----------------- */
public function takeRdvAction(){
$request = $this->get('request_stack')->getCurrentRequest();
parse_str($request->getContent(), $myArray);
/*$request->isXmlHttpRequest()*/
if (1) {
$dateHeureDispo=$myArray['heureDispo'];
$dateDispo= new \DateTime($dateHeureDispo);
$heureDispo = $dateDispo->format('H:i');
$dateDispo=$dateDispo->format('d-m-Y');
$civilite=$myArray['civilite'];
$nom=$myArray['inputNom'];
$prenom=$myArray['inputPrenom'];
$naissance=$myArray['birth'];
$email=$myArray['email'];
$tel=$myArray['tel'];
$telFixe=$myArray['telFixe'];
$adresse=$myArray['adresse'];
$cp=$myArray['cp'];
$ville=$myArray['ville'];
$pays=$myArray['pays'];
$medecin_traitant=$myArray['medecin_traitant'];
$ame=$myArray['ame'];
$cmu=$myArray['cmu'];
$takeRDv="http://connect.mysite.com/nameofapi2/takeappt?center=13&motive=238&prenom=".urlencode($prenom)."&nom=".urlencode($nom)."&email=".urlencode($email)."&birthdate=".$naissance."&address=".urlencode($adresse)."&cp=".$cp."&city=".urlencode($ville)."&country=".urlencode($pays)."&tel=".$tel."&titre=1&source=1&origine=1&daterdv=".$dateDispo."&time=".$heureDispo."&slot=1%E1%90%A7&civilite=".$civilite."&origin=smwh&referer=1";
$streamContext = stream_context_create([
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false
]
]);
$json = file_get_contents($takeRDv, false, $streamContext);
$response = new jsonResponse();
$response->setContent($json);
return $this->indexAction();
}
else {
return new response("Ajax request failed");
}
}
If I put if ($request->isXmlHttpRequest()), the controller goes directly to "else" end returns "Ajax request failed"
Ajax.js file (It's the last ajax function we are talking about):
$(document).ready(function () {
/* TakeRdvs */
$("#monBouton").click(function(){
if (nom.value != "" && prenom.value != "" && email.value != "")
{
$.ajax({
url: "{{ path('takeRdv') }}",
method: 'POST',
data: {},
success: function(data) {
$("#calendarModal").modal('hide');
$("#calendarModal").on('hidden.bs.modal', function (e) {
$('#calendar').fullCalendar('refetchEvents');
});
},
error: function(XMLHttpRequest, textStatus, errorThrown)
{
alert('Error: ' + errorThrown);
}
});
}
else if (nom.value == "")
{
alert('Veuillez renseigner le Nom');
return false;
}
else if (prenom.value == "")
{
alert('Veuillez renseigner le prénom');
return false;
}
else if (email.value == "")
{
alert("Veuillez renseigner l'adresse mail");
return false;
}
});
});
Other ajax functions work just fine, I made them after trying to take an appointment on an availability. When I implemented FosJsRouting, I thought it would be easier to try to make my takeRdvs action work. But the truth is, I don't know how to do it since it's a different action from the others and I am lost now :'(
My modal showing up when a event is clicked (got cut in several part sorry could not fix it):
×
close
<div class="form-group">
<div class="col-sm-12">
<h4 id="modalTitle" class="modal-title modify"></h4>
</div>
</div>
<div class="col-sm-4 form-group">
<label for="motif">
Motif de la consultation :
</label>
<select class="form-control" id="motif" data-placeholder="Choisissez un motif" style="width: 100%;" name="motif"> {# multiple data-max-options="1" #}
<option value="238"> Bilan de la vue</option>
<option value="Visite de controle"> Visite de contrôle</option>
<option value="Chirurgie réfractive"> Chirurgie réfractive</option>
<option value="Rééducation visuelle"> Rééducation visuelle</option>
<option value="Urgences"> Urgences</option>
</select>
</div>
<div class="form-group create">
<div class="col-sm-2">
<label class="control-label" for="civilite">Civilité</label>
<select class="custom-select" id="civilite" name="civilite">
<option value="Mme">Mme</option>
<option value="M">M.</option>
</select>
</div>
<div class="col-sm-5">
<label class="control-label" for="inputNom">Nom</label>
<input name="inputNom" type="text" class="form-control" id="inputNom" placeholder="Doe" required >
</div>
</div>
<div class="form-group">
<div class="col-sm-5 create">
<label class="control-label" for="inputPrenom">Prénom</label>
<input name="inputPrenom" type="text" class="form-control" id="inputPrenom" placeholder="Jane" required >
</div>
</div>
<div class="form-group">
<div class="col-sm-6">
<label class="control-label" for="email">Email</label>
<input name="email" type="email" class="form-control" id="email" placeholder="jane.doe#example.com" required >
</div>
</div>
{# fin de la condition #}
<div class="form-group">
<div class="col-sm-6">
<label class="control-label" for="naissance">Date de naissance</label>
<input name="birth" type="text" class="form-control" id="naissance" placeholder="01-01-2001" required>
</div>
<div class="col-sm-6">
<label class="control-label" for="tel">Mobile</label>
<input name="tel" type="tel" class="form-control" id="tel" placeholder="0607080910" required>
</div>
</div>
<div class="form-group">
<div class="col-sm-6">
<label class="control-label" for="telFixe">Téléphone fixe</label>
<input name="telFixe" type="tel" class="form-control" id="telFixe" placeholder="0101010101">
</div>
</div>
<div class="form-group">
<div class="col-sm-5">
<label class="control-label" for="adresse">Adresse</label>
<input name="adresse" type="text" class="form-control" id="adresse" placeholder="1 Bd de Strasbourg 83000 Toulon" required>
</div>
</div>
<div class="form-group">
<div class="col-sm-3">
<label class="control-label" for="cp">Code postal</label>
<input name="cp" type="text" class="form-control" id="cp" placeholder="83000" required>
</div>
</div>
<div class="form-group">
<div class="form-group">
<div class="col-sm-4">
<label class="control-label" for="ville">Ville</label>
<input name="ville" type="text" class="form-control" id="ville" placeholder="Toulon" required>
</div>
</div>
</div>
<div class="form-group">
<div class="form-group">
<div class="col-sm-4">
<label class="control-label" for="pays">Pays</label>
<input name="pays" type="text" class="form-control" id="pays" placeholder="France" required>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-6">
<label class="control-label" for="medecin_traitant">Médecin traitant</label>
<input name="medecin_traitant" type="text" class="form-control" id="medecin_traitant" placeholder="Dr Bicharzon" required>
</div>
</div>
<div class="form-group">
<div class="col-sm-6">
<label class="control-label" for="ame">
Bénéficiare de l'AME ?
</label>
<select class="form-control" name="ame" title="ame" id="ame" required>
<option value="oui">Oui</option>
<option value="non">Non</option>
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-6">
<label class="control-label" for="cmu">
Bénéficiare de la CMU ?
</label>
<select class="form-control" name="cmu" title="cmu" id="cmu" required>
<option value="oui">Oui</option>
<option value="non">Non</option>
</select>
</div>
</div>
<input title="heureDispo" class="visually-hidden form-control" name="heureDispo" type="text" id="heureDispo">
<div class="form-group boutonsModale col-sm-6">
<button type="button" class="btn btn-default btn-danger" data-dismiss="modal">Annuler</button>
<button type="submit" class="btn btn-primary" id="monBouton">Enregistrer</button>
</div>
</form>
</div>
{#{% endfor %}#}
<div class="modal-footer paddingTop">
{#<button type="button" class="btn btn-default btn-danger" data-dismiss="modal">Annuler</button>#}
{#<input type="submit" class="btn btn-primary">Enregistrer</input>#}
{#<button type="button" class="btn btn-default" data-dismiss="modal">Fermer</button>#}
</div>
</div>
</div>
</div>
</div>
Routing.yml :
Take RDV
take_rdv:
path: /prise-rdv
defaults: {_controller: RdvProBundle:Default:takeRdv}
methods: [POST]
options:
expose: true
I don't know how to change the route if I need to... + I would like the route no to show like the other routes I created but as it's coded now, it's shown...
I am junior junior as dev so I a sorry if my code is not clean :s
Thank you in advance for all the help you will provide.
It is huge. I'm not sure about your problem(s?) but if I understand :
First problem :
ajax is not working since events do not reload
If your #button is replaced in your page after your first call, the attached event is destroyed. Change your listener :
$("#monBouton").click(function(){
by
$('body').on('click', '#monBouton', function () { will solve the problem.
Second problem :
If I put if ($request->isXmlHttpRequest()), the controller goes directly to "else"
I suggest to pass $request as argument of your action and just put your condition within an if statement :
public function takeRdvAction(Request $request)
{
if ($request->isXmlHttpRequest()) {
[...]
}
}
Thirdly :
To use FosJsRouting, you exposed your route in your yaml. That's good. To use it in javascript, you have to include the given script in your base.html.twig and use Routing.generate just as defined in the doc :
$.ajax({
url: Routing.generate('take_rdv', {/* $(yourform).serialize() ?*/}),
method: 'POST',
data: {},
success: function(data) {
$("#calendarModal").modal('hide');
$("#calendarModal").on('hidden.bs.modal', function (e) {
$('#calendar').fullCalendar('refetchEvents');
});
},
error: function(XMLHttpRequest, textStatus, errorThrown)
{
alert('Error: ' + errorThrown);
}
});
Update
With my suggestions, you've to change how you use $request in your action :
$myArray = $request->request->all();
$civilite=$myArray['civilite'];
[...and so on...]
Bonus : Symfony is a powerfull framework. I suggest you to learn about using this framework and especially, in your case, about Forms
enjoy :)
UPDATE 2
if ($request->isXmlHttpRequest()) { is never true cause you are not doing an ajax call. I just see that, but your button is of type submit then, your browser send a basic HTTP request.
Add this to your js code :
$('body').on('click', '#monBouton', function (event) {
event.preventDefault();
[...$.ajax blablabla]
});

Getting text from html scope

.controller('LoginCtrl', function($scope, $rootScope, $http, $state) {
window.localStorage.removeItem("loggedIn");
if(window.localStorage.getItem("loggedIn") == undefined) {
$scope.doLogin = function() {
var username = $scope.fName + " " + $scope.lName;
console.log(username);
//store login information
window.localStorage.setItem("username", username);
window.localStorage.setItem("password", $scope.password);
window.localStorage.setItem("loggedIn", true);
$http.post('http://localhost:8000/login',{
userName: window.localStorage.getItem("username"),
password: window.localStorage.getItem("password"),
token: $rootScope.devToken,
platform: ionic.Platform.platform()
});
alert("Login Success");
$state.go('main');
};
} else {
alert("Login Success");
$state.go('main');
}
})
<ion-content ng-controller="LoginCtrl">
<form ng-submit="doLogin()" style="display: block; margin: 100px">
<div class="list">
<label class="item item-input">
<input type="text" ng-model="fName" placeholder="First Name">
</label>
<label class="item item-input">
<input type="text" ng-model="lName" placeholder="Last Name">
</label>
<label class="item item-input">
<input type="password" ng-model="password" placeholder="Password" style="text-align: center">
</label>
<label class="item">
<button class="button button-block button-positive" type="submit">Register</button>
</label>
</div>
</form>
</ion-content>
I am trying to get the text from the html field fName and lName using $scope.fName because fName is a ng-model. How come it is returning undefined? I have the controllers set properly. I just can't figure out why username is outputting undefined? I am trying to load the app up at login.html and then once logged in, it will change the state to home.html. I could really use some help doing this.
The ion-content creates its own child scope. Try declaring a main scope object in your controller:
.controller('LoginCtrl', function($scope, $rootScope, $http, $state) {
$scope.data = {}
In your template:
<input type="text" ng-model="data.fName" placeholder="First Name">
In your login submit:
var username = $scope.data.fName + " " + $scope.data.lName;
You don't have validation in place to check whether the values are actually filled or not. The scope is not populated on initialization.
If you hit submit before adding anything there is no way those values can be populated and hence they are undefined.
Do something like this in submit button.
<button class="button button-block button-positive"
type="submit" ng-disabled="!fName||!lName">Register
</button>
Good Luck.
The code implementation is found here.
https://codepen.io/anon/pen/YGzxVz
http://ionicframework.com/docs/components/#toggle
i hope this works for you. A little change with CSS will do the trick

ngSubmit HTML attribute using angular template variable

I have two methods ngMake and ngUpdate. I have one form, PostForm. I want to reuse the same form, but add different functionality depending on the url.
I gain information about the url using
Controller
if ($location.path() === '/makepost') {
$scope.FormTitle = 'Make a Post';
$scope.FormAction = 'server/blog/makepost.php';
$scope.FormMethod = 'POST';
$scope.FormSubmit = "ngMake()"
};
if ($location.path().indexOf('update') !== -1) {
$scope.FormTitle = 'Update a Post';
$scope.FormAction = null;
$scope.FormMethod = 'POST';
$scope.FormSubmit = "ngUpdate()";
};
HTML Form
<div ng-controller="BlogController as blog">
<h3 class="text-center">{{FormTitle}}</h3>
<form ng-show='user != null' ng-submit="{{FormSubmit}}" role="form" class="form-group" name="PostForm">
<label>Title: </label>
<div ng-class="(PostForm.Title.$dirty && PostForm.Title.$invalid) ? 'has-warning' : 'has-success'" class="form-group has-feedback">
<input data-ng-model="post.Title" data-ng-minlength="3" data-ng-maxlength="255" name="Title" type="text" class="form-control" placeholder="Title" required/>
<span ng-class="(PostForm.Title.$dirty && PostForm.Title.$invalid) ? 'glyphicon-warning-sign' : 'glyphicon-ok'" class="glyphicon form-control-feedback"></span>
</div>
<label>Content: </label>
<div ng-class="(PostForm.Content.$dirty && PostForm.Content.$invalid) ? 'has-warning' : 'has-success'" class="form-group has-feedback">
<textarea data-ng-model="post.Content" rows="8" name="Content" type="text" class="form-control" placeholder="Content" required></textarea>
<span ng-class="(PostForm.Content.$dirty && PostForm.Content.$invalid) ? 'glyphicon-warning-sign' : 'glyphicon-ok'" class="glyphicon form-control-feedback"></span>
</div>
<div ng-controller="AuthController as auth">
<input class="ng-hide" type="number" data-ng-model="post.UserID" name="UserID" value="{{user.ID}}">
</div>
<br>
<input type="submit" ng-class="(PostForm.$valid) ? 'btn-success' : 'disabled'" class="btn btn-block btn-default">
</form>
<p ng-show='user == null' class="text-center">You must be logged in in order to {{FormTitle | lowercase}}</p>
Explination
The {{FormSubmit}} template variable probably executes afterwards and causes a problem which doesn't permit the form to execute. I am open to suggestions, I want to reuse the same form. I read that ngSubmit requires a type="submit" button or input element contained within the form tags, I have that. I do not have any ng-clicks which might hinder the form.
I am open to suggestions
If there are any other problems with the form or the entire project please let me know, even if it is just a "bette practice".
The full project
https://github.com/AquaSolid/RAMA_Angular_PHP
Basically, I wised up. I contained the logic in the back-end. I created a function to choose which function to use. Meanwhile the the form contains the attribute ng-submit="chooseSubmit()". That's about it..
$scope.chooseSubmit = function() {
if ($scope.FormSubmit) {
if ($scope.FormSubmit === 'ngMake()') {
$scope.ngMake();
} else {
$scope.ngUpdate();
};
}
};

How can I isolate nested form?

I'm very new to AngularJS, and new to client side programming.
Context:
I'm implementing a contact form with support for multiple phone numbers and addresses.
It look like this:
<form name="contactInsertForm" ng-controller="contactInsertController as contactCtrlr" ng-submit="contactInsertForm.$valid && contactCtrlr.save()">
<input type="text" name="name" />
<phones-editor></phones-editor>
<addresses-editor></addresses-editor>
<input type="submit" />
</form>
phonesEditor and addressesEditor are custom Angular directives which implement support for adding, removing and editing phones and addresses. The controllers and modules look like this:
Addresses:
(function () {
var app = angular.module("AddressesEditorModule", []);
app.directive("addressesEditor", function () {
return {
restrict: "E",
templateUrl: "/addressesEditorTemplate.html",
controller: function ($scope) {
this.addresses = [
// this will hold addresses.
];
// ...
}
}
})();
Phones:
(function () {
var app = angular.module("PhonesEditorModule", []);
app.directive("phonesEditor", function () {
return {
restrict: "E",
templateUrl: "/phonesEditorTemplate.html",
controller: function ($scope) {
this.phones = [
// this will hold phones.
];
// ...
}
}
})();
And the templates:
Addresses:
<!-- list already added addresses -->
<div ng-repeat="address in addressesEditorCtrlr.addresses">
<p>{{address.address}}</p>
<p>{{address.city}}</p>
</div>
<form name="addressInsertForm" ng-submit="addressInsertForm.$valid && addressesEditorCtrlr.add()">
<!-- inputs for each of the address fields -->
<input type="submit" value="Add" />
</form>
Phones:
<!-- list already added phones -->
<div ng-repeat="phone in phonesEditorCtrlr.addresses">
<p>{{phone.number}}</p>
<p>{{phone.areaCode}}</p>
</div>
<form name="phoneInsertForm" ng-submit="phoneInsertForm.$valid && phonesEditorCtrlr.add()">
<!-- inputs for each of the phone fields -->
<input type="submit" value="Add" />
</form>
As you may have noticed, the generated at the browser HTML looks like this:
<form>
<input type="text" name="name" />
<phones-editor>
<!-- list already added phones -->
<div ng-repeat="phone in phonesEditorCtrlr.addresses">
<p>{{phone.number}}</p>
<p>{{phone.areaCode}}</p>
</div>
<form name="phoneInsertForm" ng-submit="phoneInsertForm.$valid && phonesEditorCtrlr.add()">
<!-- inputs for each of the phone fields -->
<input type="submit" value="Add" />
</form>
</phones-editor>
<addresses-editor>
<!-- list already added addresses -->
<div ng-repeat="address in addressesEditorCtrlr.addresses">
<p>{{address.address}}</p>
<p>{{address.city}}</p>
</div>
<form name="addressInsertForm" ng-submit="addressInsertForm.$valid && addressesEditorCtrlr.add()">
<!-- inputs for each of the address fields -->
<input type="submit" value="Add" />
</form>
</addresses-editor>
</form>
The problem:
I have two form's inside a form. The nested forms work correctly, adding and validating values it should be doing, and refusing to add invalid phones/addresses.
But when I click the submit button at the outer form, it will interpret the inner forms input fields and will raise errors if these fields have invalid values.
How can I use AngularJS form handling and avoid this situation? Is this possible at all?
you would need a directive if you want child form as isolate form. Have a look at answers from this SO question. please have a look at fiddle attached in this answer. I am putting the fiddle link here for you to js-fiddle to see it in action.
putting below code just because SO doesnt accept only fiddle links...
<form name="parent">
<input type="text" ng-model="outside"/>
<ng-form name="subform" isolate-form>
<input type="text" ng-model="inside"/>
</ng-form>
</form>
Working on Angular 1.6
const isolatedFormDirective = () => {
return {
restrict: 'A',
require: '?form',
link: ($scope, $element, $attrs, ctrl) => {
ctrl && ctrl.$$parentForm && ctrl.$$parentForm.$removeControl(ctrl);
}
}
}
app.directive('isolatedForm', isolatedFormDirective);
This article has exactly what you are looking for.
The basic gist is that you want to use the ngForm directive inside your form tag.
<div ng-form="outerForm">
<input type="text" ng-model="main.outerFormText"/>
<div ng-form="innerForm">
<input type="text" ng-model="main.innerFormText" required/>
<button type="button" ng-click="main.submit('innerForm')"
ng-disabled="innerForm.$invalid">Inner Submit</button>
</div>
<button type="button" ng-click="main.submit('outerForm')"
ng-disabled="outerForm.$invalid">Outer Submit</button>
</div>
Example plnkr