How to validate forms in modal with tabs and angularJs - angularjs

I have a modal form with angular and uib-tabset.
I have only a footer in modal.
Each tabset has a form( A B and C).
When I try enabled/disable the save button on footer, I can´t acesss
acesss the forms. They are undefined.
So, in the 'Save' button(see plunker) - formA.$invalid doesn´t works. I think it is a scope problem.
I´d prefer doesn´t put a global form to all tabs.
Is there some workaround to solve it?
Markup:
<div class="modal-content">
<div class="modal-header bg-primary">
<button type="button" class="close" ng-click="doCancel()" aria-hidden="true">×</button>
<h4 class="modal-title" id="ativarSmsLabel">
Test
</h4>
</div>
<div class="modal-body">
<uib-tabset active="activePill" vertical="false" type="pills">
<uib-tab index="0" heading="Agendamento">
<form name="formA" novalidate>
<input type="text" ng-model="testA"
</form>
</div>
</div>
</div>
</uib-tab>
<uib-tab index="1" heading="Ficha">
<form name="formB" novalidate>
<input type="text" ng-model="testB"
</form>
</uib-tab>
<uib-tab index="2" heading="Histórico">
<form name="formC" novalidate>
<input type="text" ng-model="testC"
</form>
</uib-tab>
</uib-tabset>
</div>
<div class="modal-footer">
<div class="btn-toolbar">
<button type="button" class="btn btn-sm btn-primary pull-right" ng-click="saveItem()"
aria-hidden="true" ng-disabled="formA.$invalid">
Save
</button>
<button type="button" class="btn btn-sm pull-right" ng-click="doCancel()"
aria-hidden="true">
Close
</button>
</div>
</div>
</div>

Core AngularJS directives such as ng-repeat, ng-switch, ng-view, ng-include and ng-if all create new child scopes. As a result, the form controller will attach its API to that child scope. In this case the uib-tabset directive is transcluding to a child scope.
To access form controls on the parent scope, use the ng-form directive to create a nested form:
<form name="top">
<div ng-if="AngularExpression">
<ng-form name="formA" novalidate>
<input ng-model="userData.testA" required />
</ng-form>
</div>
</form>
<div ng-show="top.formA.$error.$required">
ERROR: input required
</div>
Also it is important to follow the "best practice" of always have a dot, '.', in your ng-models.
For more information, see What are the nuances of scope prototypal / prototypical inheritance in AngularJS?.

Related

Form validation with Bootstrap 4 and AngularJS

I have a form made with Bootstrap 4 and AngularJS and I want to make a simple form validation where I could:
validate input fields AFTER user has touched them,
show two different error messages depending on validation constraint,
create custom validation constraint (e.g. compare password and password confirmation field).
1.
In previous versions of Bootstrap you could do something like:
<div class="form-group" ng-class="{'has-error': userForm.email.$invalid && userForm.email.$touched}">
but with Bootstrap 4, there is no 'has-error' class. I tried to use 'is-invalid' class instead
<div class="form-group" ng-class="{'is-invalid': userForm.email.$invalid && userForm.email.$touched}">
but nothing happens. I managed to make it work as it is shown in Bootstrap 4 Documentation but validation happens only after the form submission and not when user has touched the input field.
2.
There are no error messages in Bootstrap 4, only 'invalid-feedback' and I can't figure out how to change message text depending on which constraint was violated. I tried something like:
<div class="invalid-feedback">
<p ng-show="userForm.email.$error.required">Required</p>
<p ng-show="userForm.email.$error.email">Enter a valid email</p>
</div>
but this does not work.
3.
I tried to make an Angular directive but because 1. and 2. didn't work I couldn't test this.
Any help will be appreciated.
UPDATE
As Peter Wilson suggested, nothing was wrong with my code. The code didn't work because my form was in a modal window and modal window must have a separate controller in AngularJS to be able to work correctly.
the is-invalid class is the right answer you may have another problem with your form so check my below demo
Note to test touched input you have to focus on the input and then leave focus to trigger touched state
angular.module('myApp',[])
.controller('myCtrl',function(){
})
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.js"></script>
<div ng-app="myApp" class="container">
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
Launch demo modal
</button>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div ng-controller="myCtrl" class="container">
<form name="loginForm" novalidate>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" ng-model="email" required class="form-control" name="email" ng-class="{'is-invalid':loginForm.email.$error.required && loginForm.email.$touched}" placeholder="Enter email">
<small ng-show="loginForm.email.$error.required && loginForm.email.$touched" id="emailHelp" class="form-text text-danger">email is required.</small>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</div>

How to use ng-model, in a modal. angularjs?

I have the following modal, With ng-model item
<div class="uk-modal" id="modal_header_footer">
<div class="uk-modal-dialog">
<div class="uk-modal-header">
<h3 class="uk-modal-title">Editar Usuario</h3>
</div>
<form id="form_validation" class="uk-form-stacked">
<div class="uk-grid" data-uk-grid-margin>
<div class="uk-width-medium-1-2">
<div class="parsley-row">
<label for="fullname">user<span class="req">*</span></label>
<input type="text" ng-model="item.user" required class="md-input" md-input />
</div>
</div>
<div class="uk-width-medium-1-2">
<div class="parsley-row">
<label for="fullname">name<span class="req">*</span></label>
<input id="nombre" type="text" name="nombre" ng-model="item.name" required class="md-input" md-input />
</div>
</div>
</div>
<div class="uk-grid" data-uk-grid-margin>
<div class="uk-width-medium-1-2">
<div class="parsley-row">
<label for="email">Email<span class="req">*</span></label>
<input id="email" type="email" name="email" ng-model="item.email" data-parsley-trigger="change" required class="md-input" md-input />
</div>
</div>
</div>
</form>
<div class="uk-modal-footer uk-text-right">
<button type="button" class="md-btn md-btn-flat uk-modal-close">Cerrar</button>
<button type="button" ng-click="EditarUsuario(item)" class="md-btn md-btn-flat md-btn-flat-primary">Aceptar</button>
</div>
</div>
The modal call it from a button belonging to a record in datatable, "data-uk-modal="{target:\'#modal_header_footer\'}""
vm.dtColumns = [
DTColumnBuilder.newColumn('id').withTitle('Id'),
DTColumnBuilder.newColumn('usuario').withTitle('Usuario'),
DTColumnBuilder.newColumn('nombre').withTitle('Nombre'),
DTColumnBuilder.newColumn('email').withTitle('Email'),
DTColumnBuilder.newColumn('telefono').withTitle('Telefono'),
DTColumnBuilder.newColumn('estado').withTitle('Estado'),
DTColumnBuilder.newColumn('created_at').withTitle('Creado'),
DTColumnBuilder.newColumn(null).withClass('parent').withTitle('Acciones').notSortable().renderWith(function(data,type,full){
vm.usuario[data.id] = data;
return ' <i class="md-icon material-icons md-bg-light-blue-900 uk-text-contrast"></i>'+
' <i class="md-icon material-icons md-bg-red-900 uk-text-contrast"></i>';
})
];
I need to pass the data parameter, and so make use of the ng-model in the modal
There is no difference between the way we use ng-model in a modal and any other part of the website.
In your case, I suppose you want to show the user's data displayed which belong to a specific record in the table.
So if your ng-model in the modal belongs to the same controller which contains the edit func, you just need to bind the information passed as parameter to the corresponding ng-model in the modal. When the modal shows up, it will show the bind information in the modal.
Let's say, in your modal you have this:
<div class="parsley-row">
<label for="fullname">user<span class="req">*</span></label>
<input type="text" ng-model="item.user" required class="md-input" md-input />
</div>
Then in your edit function you just have to say
function edit(user){
$scope.item = user; //...item is the var used for binding the information to the modal and user is the var coming from the table
}
This can solved using dummy object. here is a code
<td title="'Payment'"> <button type="button" class="btn btn-info btn-lg pay-btn" data-toggle="modal" data-target="#myModal" ng-click="mommy(obj)" >yuty</button>
<!-- Modal content-->
<div id="myModal" class="modal fade" role="dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-body">
<form>
<div class="form-group">
<label>Amout</label>
<input type="Number" ng-model="vvv.payment">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal" ng- click="mono=false">Close</button>
<button type="button" class="btn btn-default" ng- click="modify(vvv._id,vvv)">Submit</button>
</div>
</div>
dummy object
$scope.mommy = function(h){
console.log(h.payment);
$scope.vvv = h;
}
hope you get to understand it,
This is better way to use it

How to get popup when url status success in angular js

I am doing an event scheduler app using angular js. In calendar when i am clicking the event i am sent the event id to back end to getting event details.Here how to get the pop up on my calendar when the url status is true.
My code is:
$scope.alertOnEventClick = function( date, jsEvent, view){
var event_id=date.id;
$http.post("Youin-api/v2/business/event_information",{"event_id":event_id}).then(function(response) {
if(response.error="true")
{
$scope.eventInformation= response;
}
});
};
My bootstrap model pop up is:
<div class="modal fade" id="AddUsers" ng-model="eventInformation" role="dialog">
<div class="modal-dialog " style="top:80px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">User Details</h4>
</div>
<div class="modal-body">
<p><form role="form" ng-submit="AddUsers(addusers)">
<div class="form-group">
<label for="pwd">User Type</label>
<input type="text" class="form-control" id="user_type" ng-model="addusers.user_type" value="{{addusers.user_type}}">
</div>
<div class="form-group">
<label for="pwd">Created By</label>
<input ty{{addusers.user_type}}pe="text" class="form-control" id="created_by" ng-model="addusers.created_by" value="">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-default">Submit</button>
</div>
</form></p>
</div>
</div>
</div>
</div>
thanks in advance..!!
To manually trigger modal to show from javascript. Use this.
$('#AddUsers').modal('show')
Note: You have to add bootstrap.js and jquery.js to use this functionality.
You can view the complete modal api options here.
Wherever you want to open the modal based on your condition you can achieve the same using following:
angular.element(document.getElementById("AddUsers")).modal();

form-control attribute is not adjusting to bootstrap modal template

I am trying to create a modal with form using angularjs and bootstrap.
First I created the form and now I am trying to put it to modal template but the form-control is sliding out of the modal as you can see in the link attached.
<div class="modal-header">
<h3 class="modal-title">Add New Review</h3>
</div>
<div class="modal-body">
<form role="form">
<fieldset>
<legend>Basic Information</legend>
<div class="container">
<div class="form-group">
<label for="address">Address</label>
<input type="text" id="address" name="address" class="form-control col-sm-1"
ng-model="editableReview.address"
required>
</div>`enter code here`
</fieldset>
</form>
</div>
<div class="modal-footer">
<div class="col-sm-offset-10">
<input type="button" class="btn btn-default" value="Cancel" ng-click="cancelForm()"/>
<input type="submit" class="btn btn-primary" value="Submit" ng-click="submitForm()"/>
</div>
</div>
this is what I get:
It seems like your problem is with the div class, specifically the container. I think you should try to delete this line:
<div class="container">
(and ofcourse its closing tag: </div>, and see if it fixes your issue.
Let me know if that helps.

use form under another form with seprate button

I want use a form under another form in angularjs. First form (form1) is a form-wizard. I want use another form in form1 and then goto another step of form-wizard. I want add some data in form2 and push data in a list and then by form 1, goto another step. I have below code:
<form class="tab-pane" id="second-1" name="second-1Form" rc-submit rc-step>
<form ng-submit="form2()">
<div class="form-group">
...
</div>
<div class="form-group">
...
</div>
<div class="form-group">
<button>Submit</button>
</div>
</form>
</form>
<div class="form-group">
<div class="pull-right">
<a class="btn btn-default" ng-click="rc.sampleWizard.backward()"ng-show="rc.sampleWizard.currentIndex > rc.sampleWizard.firstIndex">Back</a>
<a class="btn btn-primary" data-loading-text="Please Wait..." ng-click="rc.sampleWizard.forward()"ng-show="rc.sampleWizard.currentIndex < rc.sampleWizard.navigationLength">Continue</a>
<a class="btn btn-primary" ng-click="rc.sampleWizard.forward()"ng-show="rc.sampleWizard.currentIndex == rc.sampleWizard.navigationLength">Complete</a>
</div>
</div>
and in controller:
$scope.addBolouk = function(){
$scope.BoloukRadif.push($scope.formdata);
};
but when I complete form2 and click on submit, data don't add to list and submit of form-wizard is work and page is goto next form-wizrd.
I want add data to list by using first form and then goto next form-wizard. How can I seprate button of form2 from button of form-wizard? How can I resolve this problem?
You can't have a form inside a form, but you can use the ng-form directive,
<form class="tab-pane" id="second-1" name="second-1Form" rc-submit rc-step>
<ng-form>
<div class="form-group">
...
</div>
<div class="form-group">
...
</div>
<div class="form-group">
<button ng-click="form2()">Submit</button>
</div>
</ng-form>
</form>
<div class="form-group">
<div class="pull-right">
<a class="btn btn-default" ng-click="rc.sampleWizard.backward()"ng-show="rc.sampleWizard.currentIndex > rc.sampleWizard.firstIndex">Back</a>
<a class="btn btn-primary" data-loading-text="Please Wait..." ng-click="rc.sampleWizard.forward()"ng-show="rc.sampleWizard.currentIndex < rc.sampleWizard.navigationLength">Continue</a>
<a class="btn btn-primary" ng-click="rc.sampleWizard.forward()"ng-show="rc.sampleWizard.currentIndex == rc.sampleWizard.navigationLength">Complete</a>
</div>
</div>

Resources