How to clear directive ngmodel value from controller? - angularjs

I am newbie in angularjs. I have create directive called newActivity and bind object, variables and function with this directive. Here i want that when i clicked on submit/cancel button then it should clear all ng-model bind variables from both newActivity directive and from controller.
Example
Directive:-
angular
.module('app')
.directive('newActivity', newActivity);
function newActivity() {
var directive = {
restrict: 'E',
scope: {
newActivity: '=',
underUsers: '=',
actTypes: '=',
callTypes: '=',
forAct: '#',
action: '&',
cancel: '&'
},
template: '<div class="box-header"> <h2>{{forAct}} {{newActivity.type | uppercase}} Activity</h2> </div> <div class="box-divider m-a-0">' +
'</div> <div class="box-body"> <form ng-submit="action()" name="newActForm" role="form">' +
'<div class="form-group row"><div class="col-sm-10"><select class="form-control" ng-model="newActivity.type" ng-options="actType.type as actType.title for actType in actTypes"></select></div></div> ' +
'<div ng-if="newActivity.type==\'notes\'" class="form-group row"><div class="col-sm-10"><textarea required ng-model="newActivity.description" class="form-control" rows="2"></textarea></div></div> ' +
'<div ng-if="newActivity.type==\'meeting\' || newActivity.type==\'email\' || newActivity.type==\'task\'" class="form-group row"><div class="col-sm-10">' +
'<div class="form-group row"><div class="col-sm-10"><input required placeholder="Select Date" type="text" class="form-control w-auto inline" ng-model="newActivity.date" data-date-format="dd-MM-yyyy" data-autoclose="true" data-date-type="number" data-icon-left="fa fa-chevron-left" data-icon-right="fa fa-chevron-right" placeholder="From" bs-datepicker></div></div>' +
'<div class="form-group row"><div class="col-sm-10"><input required placeholder="Select Time" type="text" class="form-control" ng-model="newActivity.time" data-time-format="HH:mm" data-time-type="number" name="time2" data-icon-up="fa fa-chevron-up" data-icon-down="fa fa-chevron-down" bs-timepicker></div></div>' +
'<div class="form-group row"> <label class="col-sm-4 form-control-label">Reminder</label> <div class="col-sm-8"> <div class="checkbox"> <label class="ui-switch m-t-xs m-r"> <input type="checkbox" ng-model="newActivity.isReminder" value=""> <i></i> </label> </div> </div> </div>' +
'<div ng-if="newActivity.isReminder" col-sm-8>' +
'<div class="form-group row"><div class="col-sm-10"><input required placeholder="Reminder Date" type="text" class="form-control w-auto inline" ng-model="newActivity.reminder.date" data-icon-left="fa fa-chevron-left" data-date-format="dd-MM-yyyy" data-autoclose="true" data-date-type="number" data-icon-right="fa fa-chevron-right" placeholder="From" bs-datepicker></div></div> ' +
'<div class="form-group row"><div class="col-sm-10"><input required placeholder="Reminder Time" type="text" class="form-control" ng-model="newActivity.reminder.time" data-time-format="HH:mm" data-time-type="number" name="time1" data-icon-up="fa fa-chevron-up" data-icon-down="fa fa-chevron-down" bs-timepicker></div></div> ' +
'</div>' +
'<div class="form-group row"> <label class="col-sm-4 form-control-label">Assign To Other</label> <div class="col-sm-8"> <div class="checkbox"> <label class="ui-switch m-t-xs m-r"> <input type="checkbox" ng-model="newActivity.isAssignOther" value=""> <i></i> </label> </div> </div> </div>' +
'<div ng-if="newActivity.isAssignOther" col-sm-8>' +
'<div class="form-group row"><div class="col-sm-10"><select class="form-control" ng-model="newActivity.assignTo" ng-options="user._id as user.name for user in underUsers"></select></div></div> ' +
'</div>' +
'<div class="form-group row"><div class="col-sm-10"><textarea required placeholder="Remarks" class="form-control" ng-model="newActivity.description" rows="2"></textarea></div></div>' +
'</div></div> ' +
'<div ng-if="newActivity.type==\'call\'" class="form-group row"><div class="col-sm-10">' +
'<div class="form-group row"><div class="col-sm-10"><select class="form-control" ng-init="newActivity.callType = \'out\'" ng-model="newActivity.callType" ng-options="callType.type as callType.title for callType in callTypes"></select></div></div>' +
'<div class="form-group row"><div class="col-sm-10"><input required placeholder="Select Date" type="text" class="form-control w-auto inline" ng-model="newActivity.date" data-date-format="dd-MM-yyyy" data-autoclose="true" data-date-type="number" data-icon-left="fa fa-chevron-left" data-icon-right="fa fa-chevron-right" placeholder="From" bs-datepicker></div></div>' +
'<div class="form-group row"><div class="col-sm-10"><input required placeholder="Select Time" type="text" class="form-control" ng-model="newActivity.time" data-time-format="HH:mm" data-time-type="number" name="time2" data-icon-up="fa fa-chevron-up" data-icon-down="fa fa-chevron-down" bs-timepicker></div></div>' +
'<div class="form-group row"> <label class="col-sm-4 form-control-label">Reminder</label> <div class="col-sm-8"> <div class="checkbox"> <label class="ui-switch m-t-xs m-r"> <input type="checkbox" ng-model="newActivity.isReminder" value=""> <i></i> </label> </div> </div> </div>' +
'<div ng-if="newActivity.isReminder" col-sm-8>' +
'<div class="form-group row"><div class="col-sm-10"><input required placeholder="Reminder Date" type="text" class="form-control w-auto inline" ng-model="newActivity.reminder.date" data-icon-left="fa fa-chevron-left" data-date-format="dd-MM-yyyy" data-autoclose="true" data-date-type="number" data-icon-right="fa fa-chevron-right" placeholder="From" bs-datepicker></div></div> ' +
'<div class="form-group row"><div class="col-sm-10"><input required placeholder="Reminder Time" type="text" class="form-control" ng-model="newActivity.reminder.time" data-time-format="HH:mm" data-time-type="number" name="time1" data-icon-up="fa fa-chevron-up" data-icon-down="fa fa-chevron-down" bs-timepicker></div></div> ' +
'</div>' +
'<div class="form-group row"> <label class="col-sm-4 form-control-label">Assign To Other</label> <div class="col-sm-8"> <div class="checkbox"> <label class="ui-switch m-t-xs m-r"> <input type="checkbox" ng-model="newActivity.isAssignOther" value=""> <i></i> </label> </div> </div> </div>' +
'<div ng-if="newActivity.isAssignOther" col-sm-8>' +
'<div class="form-group row"><div class="col-sm-10"><select class="form-control" ng-model="newActivity.assignTo" ng-options="user._id as user.name for user in underUsers"></select></div></div> ' +
'</div>' +
'<div class="form-group row"><div class="col-sm-10"><textarea required placeholder="Remarks" class="form-control" ng-model="newActivity.description" rows="2"></textarea></div></div>' +
'</div></div> ' +
'<div class="form-group row m-t-md"> <div class="col-sm-offset-2 col-sm-10">' +
'<input type="submit" class="btn success" value="Save">' +
'<button type="button" style="margin-left:5px" ng-click="cancel()" class="btn danger">Cancel</button>' +
'</div></form> </div>',
link: function(scope, element, attrs) {},
controller: function($scope) {}
};
return directive;
}
Controller:-
function addNewActivity() {
vm.loading = true;
vm.newActivity = {}; //Here vm.newActivity is not clear fields from "newActivity" directive
}
HTML:-
<new-activity for-act='Add' action='addNewActivity()' cancel='closeAddNewActivity()' new-activity='newActivity' under-users='underUsers' act-types='actTypes' call-types='callTypes'></new-activity>

You are using the controllerAs synthax, you should prefix your calls to functions and use of variables with the name you specify (here vm).
For example if your code:
<new-activity for-act='Add'
action='addNewActivity()'
cancel='closeAddNewActivity()'
new-activity='newActivity'
under-users='underUsers'
act-types='actTypes'
call-types='callTypes'>
</new-activity>
Shoud be:
<new-activity for-act='Add'
action='vm.addNewActivity()'
cancel='vm.closeAddNewActivity()'
new-activity='vm.newActivity'
under-users='vm.underUsers'
act-types='vm.actTypes'
call-types='vm.callTypes'>
</new-activity>

Use new-activity='vm.newActivity' instead of new-activity='newActivity
And also use vm.addNewActivity() and vm.closeAddNewActivity()
So that every bindings have the correct source from your controller
<new-activity for-act='Add' action='vm.addNewActivity()' cancel='vm.closeAddNewActivity()' new-activity='vm.newActivity' under-users='vm.underUsers' act-types='vm.actTypes' call-types='vm.callTypes'></new-activity>

Related

Dynamically creating ng-model values

I am building out a debt consolidation calculator that has two tables that allows the user to add and remove rows. The rows contain 4 inputs for different values:
code plunker: plnkr.co/edit/AS6M8zi3VrqKKgfTGwVT?p=preview
HTML
.directive('cuDebtConsolidation',
function() {
return {
restrict: 'E',
scope: false,
template:
'<div id="debtConsolidationPrint">' +
'<form name="debtConsolidationForm" role="form" data-toggle="validator" novalidate>' +
'<div class="row mb-3 mt-5 mx-auto calcRow">' +
'<div class="col m-3">' +
'<div ng-repeat="table in tables">' +
'<h3 class="mt-4">{{table.name}}</h3>' +
'<table>' +
'<thead>' +
'<tr>' +
'<th>Loan Name</th>' +
'<th>Remaining Balance</th>' +
'<th>Monthly Payment</th>' +
'<th>Loan Term</th>' +
'</tr>' +
'</thead>' +
'<tbody>' +
'<tr ng-repeat="(rowIndex, row) in table.rows" name="{{row.name}}">' +
'<td><input class="form-control form-control-md text-transform-none" title="Please Enter loan name" maxlength="7" required type="text"></td>' +
'<td><input class="form-control form-control-md text-transform-none" title="Please Enter remaining balance" maxlength="7" required type="number"></td>' +
'<td><input class="form-control form-control-md text-transform-none" title="Please Enter Monthly Payment" maxlength="7" required type="number"></td>' +
'<td><input class="form-control form-control-md text-transform-none" title="Please Enter loan term" maxlength="7" required type="number" ></td>' +
'<td><input type="button" class="btn btn-round btn-sm btn-brand" value="Remove" ng-click="removeRow(rowIndex, table)"/></td>' +
'</tr>' +
'</tbody>' +
'</table>' +
'<button class="btn btn-round btn-sm btn-brand mt-2" ng-click="addRow(table)">Add Row</button>' +
'</div>' +
'<div class="d-flex">' +
'<button class="btn btn-round btn-lg btn-brand d-block mt-2 w-100" ng-click="debtConsolidation();">Calculate!</button>' +
'</div>' +
'</div>' +
'</div>' +
'</form>' +
'</div>'
};
});
Controller:
$scope.tables=[{name: "Installment Table"}, {name: "Credit Card Table"}];
$scope.tables[0].rows = [{name: "row1"}];
$scope.tables[1].rows = [{name: "row1"}];
$scope.counter = 2;
$scope.addRow = function(table) {
table.rows.push({ name: "row" + $scope.counter});
$scope.counter++;
};
$scope.removeRow = function(rowIndex, table) {
table.rows.splice(rowIndex, 1);
};
$scope.debtConsolidation = function() {
console.log($scope.debtConsolidationForm);
};
I use ng-repeat to loop over the two tables and then ng-repeat to loop over the rows. This is all within a form, I'm try to ng-click="debtConsolidation();" run calculations but i cant seem to figure out how to bind the dynamic inputs to then be able to use the data from each dynamic row.
You can give each input an ng-model attribute. This will put a value property on your $scope.tables.rows object.
Here's an example:
'<tbody>' +
'<tr ng-repeat="(rowIndex, row) in table.rows" name="{{row.name}}">' +
'<td><input ng-model="row.loanName" class="form-control form-control-md text-transform-none" title="Please Enter loan name" maxlength="7" required type="text"></td>' +
'<td><input ng-model="row.remainingBalance" class="form-control form-control-md text-transform-none" title="Please Enter remaining balance" maxlength="7" required type="number"></td>' +
'<td><input ng-model="row.monthlyPayment" class="form-control form-control-md text-transform-none" title="Please Enter Monthly Payment" maxlength="7" required type="number"></td>' +
'<td><input ng-model="row.loanTerm" class="form-control form-control-md text-transform-none" title="Please Enter loan term" maxlength="7" required type="number" ></td>' +
'<td><input type="button" class="btn btn-round btn-sm btn-brand" value="Remove" ng-click="removeRow(rowIndex, table)"/></td>' +
'</tr>' +
'</tbody>'
And if you console.log the object in the $scope.debtConsolidation function, you can see the object.

Angular ng-options rendering twice for scope variable

I'm running into a really weird situation using ng-options inside a directive. Ideally, I'm trying to render a list of the 50 US States, but I'm running into the issue no matter what I fill the array with. Basically It's rendering each select option twice, as if it went through the loop twice, I'm using Angular 1.6.3 and webpack:
Directive:
var ctrl = function($scope){
// $scope.states_list = statesList
$scope.states_list = [
{ abbr : 'A', name : 'Test A' },
{ abbr : 'B', name : 'Test B' },
{ abbr : 'C', name : 'Test C' },
]
$scope.init = function(){
// $scope.states_list = statesList
}
}
var directive = function(){
return {
restrict : 'E',
templateUrl : '/templates/forms/address',
controller : ctrl,
// transclude: true,
// require: 'ngModel',
replace : true,
scope : {
form : '=',
address : '='
}
}
}
module.exports = function(app){
app.directive('addressForm', directive)
}
Template: (In Jade/Pug)
div(ng-init="init()")
.row: .form-group.col-md-12(validate-field="form.name", error-message="Please enter a name")
label.control-label Name
input.form-control(name='name', placeholder='Name', type='text', required, ng-model="address.name")
.row: .form-group.col-md-12(validate-field="form.address1", error-message="Please enter an address")
label.control-label Address
input.form-control(name='address1', placeholder='Address', type='text', required, ng-model="address.address1")
.row: .form-group.col-md-12
label.control-label Address2
input.form-control(name='address2', placeholder='Address2', type='text', ng-model="address.address2")
.row
.form-group.col-md-6(validate-field="form.city", error-message="Please enter a city")
label.control-label City
input.form-control(name='city', placeholder='City', type='text', required, ng-model="address.city")
.form-group.col-md-3(validate-field="form.state", error-message="Please select a state")
label.control-label State / Province
select.form-control(name="state", ng-model="address.state", ng-options="st.abbr as st.name for st in states_list")
option(value="") -- Select a State --
.form-group.col-md-3(validate-field="form.postal_code", error-message="Please enter a valid ZIP Code")
label.control-label Postal/ZIP Code
input.form-control(name='postal_code', placeholder='Postal/ZIP Code', type='text', required, ng-model="address.postal_code")
input(type="hidden", name="country", value="US", ng-model="address.country")
Results:
<div ng-init="init()" address="delivery" form="ctrl.shipping_form" class="ng-isolate-scope">
<div class="row">
<div error-message="Please enter a name" class="form-group col-md-12 ng-scope" ng-class="{ 'has-error': form.name.$dirty && form.name.$invalid }" tooltip-trigger="'none'" uib-tooltip="Please enter a name" tooltip-is-open="form.name.$dirty && form.name.$invalid">
<label class="control-label">Name</label>
<input name="name" placeholder="Name" type="text" required="required" ng-model="address.name" class="form-control ng-pristine ng-untouched ng-empty ng-invalid ng-invalid-required">
</div>
</div>
<div class="row">
<div error-message="Please enter an address" class="form-group col-md-12 ng-scope" ng-class="{ 'has-error': form.address1.$dirty && form.address1.$invalid }" tooltip-trigger="'none'" uib-tooltip="Please enter an address" tooltip-is-open="form.address1.$dirty && form.address1.$invalid">
<label class="control-label">Address</label>
<input name="address1" placeholder="Address" type="text" required="required" ng-model="address.address1" class="form-control ng-pristine ng-untouched ng-empty ng-invalid ng-invalid-required">
</div>
</div>
<div class="row">
<div class="form-group col-md-12">
<label class="control-label">Address2</label>
<input name="address2" placeholder="Address2" type="text" ng-model="address.address2" class="form-control ng-pristine ng-untouched ng-valid ng-empty">
</div>
</div>
<div class="row">
<div error-message="Please enter a city" class="form-group col-md-6 ng-scope" ng-class="{ 'has-error': form.city.$dirty && form.city.$invalid }" tooltip-trigger="'none'" uib-tooltip="Please enter a city" tooltip-is-open="form.city.$dirty && form.city.$invalid">
<label class="control-label">City</label>
<input name="city" placeholder="City" type="text" required="required" ng-model="address.city" class="form-control ng-pristine ng-untouched ng-empty ng-invalid ng-invalid-required">
</div>
<div error-message="Please select a state" class="form-group col-md-3 ng-scope" ng-class="{ 'has-error': form.state.$dirty && form.state.$invalid }" tooltip-trigger="'none'" uib-tooltip="Please select a state" tooltip-is-open="form.state.$dirty && form.state.$invalid">
<label class="control-label">State / Province</label>
<select name="state" ng-model="address.state" ng-options="st.abbr as st.name for st in states_list" class="form-control ng-pristine ng-valid ng-empty ng-touched">
<option value="" class="" selected="selected">-- Select a State --</option>
<option label="Test A" value="string:A">Test A</option>
<option label="Test B" value="string:B">Test B</option>
<option label="Test C" value="string:C">Test C</option>
<option label="Test A" value="string:A">Test A</option>
<option label="Test B" value="string:B">Test B</option>
<option label="Test C" value="string:C">Test C</option>
</select>
</div>
<div error-message="Please enter a valid ZIP Code" class="form-group col-md-3 ng-scope" ng-class="{ 'has-error': form.postal_code.$dirty && form.postal_code.$invalid }" tooltip-trigger="'none'" uib-tooltip="Please enter a valid ZIP Code" tooltip-is-open="form.postal_code.$dirty && form.postal_code.$invalid">
<label class="control-label">Postal/ZIP Code</label>
<input name="postal_code" placeholder="Postal/ZIP Code" type="text" required="required" ng-model="address.postal_code" class="form-control ng-pristine ng-untouched ng-empty ng-invalid ng-invalid-required">
</div>
<input type="hidden" name="country" value="US" ng-model="address.country" autocomplete="off" class="ng-pristine ng-untouched ng-valid ng-empty">
</div>
</div>
Any thoughts? Thanks in advance for the help.

How to validate forms in Angular JS

i'm a newbie in angular JS. and i was trying the input type="text", i'm retrieving my name from my controller and i was using $dirty and $invalid to validate my data but it isn't showing when i make the input field empty.
JS Fiddle : https://jsfiddle.net/U3pVM/24718/
var FormValidations = angular.module('FormValidations',[]);
FormValidations.controller('FormsValidations', function( $scope ){
$scope.formsToBeValidated = {
firstName : 'Daniel'
};
});
Unless you add name attribute to form level field, that will not get included in form object when you specified in the name attribute on form, currentlyh it is name="studentForm". Do add name="firstName" to your input field
<input type="text" class="form-control"
name="firstName" ng-model="formsToBeValidated.firstName" required/>
Forked Fiddle
For more information you could refer this answer, which has more detailed
More convenient way to solve this issue would be using ng-messages instead of using ng-show/ng-hide, for that you have to include ng-messages module with its ng-messages dependency.
you should try this:
<input name="firstName" type="text" class="form-control"
ng-model="formsToBeValidated.firstName" required>
fiddle
as other says , add "name" attribute to your input.
I made a custom directive to display error on input using ng-message ( so you have to include it )
directives.directive('inputerrormsg', function () {
return {
replace: true,
restrict: 'E',
plain: true,
scope: {
inputdata: "=",
dpattern: '#'
},
template: '<div class="help-block has-error text-center" ng-messages="inputdata[\'$error\']" >' +
'<p ng-message="required">{{\'The field is required\'| translate }}</p>' +
'<p ng-message="minlength">{{\'Input too short\'| translate }}</p>' +
'<p ng-message="maxlength">{{\'Input too long\'| translate }}</p>' +
'<p ng-message="email">{{\'Email invalid\'| translate }}</p>' +
'<p ng-message="date">{{\'Date invalid\'| translate }}</p>' +
'<p ng-message="number">{{\'Write number only\'| translate }}</p>' +
'<p ng-message="pattern">' +
'<span ng-switch="dpattern">' +
'<span ng-switch-when="date">{{\'Date incorrecte: YYYY, YYYY/MM, YYYY/MM/DD\' |translate}}</span>' +
'<span ng-switch-default>{{\'Saisir uniquement des lettres\'| translate }}</span>' +
'</span>' +
'</p>' +
'</div>'
}
});
USAGE :
required field
<div style="padding-left: 0px;" ng-class="{ 'has-error' : !formDeter.scientificname.$valid">
<div class="input-group no-padding">
<input type="text"
class="form-control input-md" name="scientificname"
required />
<span class="input-group-addon">
<span class="glyphicon glyphicon-question-sign"></span>
</span>
</div>
<dir.inputerrormsg inputdata="formDeter.scientificname" ></dir.inputerrormsg>
EMail :
<div class="form-group row" ng-class="{ 'has-error' : !formData.email.$valid }">
<label class="col-xs-4 control-label">{{"Email" | translate }}</label>
<div class="col-xs-8 input-group">
<input type="email" class="form-control input-md" ng-model="email" name="email" id="email" required
placeholder="{{'Email' | translate }}"/>
</div>
<dir.inputerrormsg inputdata="formData.email" dpattern="email" ></dir.inputerrormsg>
</div>
Number only :
<div class="form-group row" ng-class="{ 'has-error' : !formLocalisation.decimallongitude.$valid }">
<label class="col-xs-4 control-label">{{"Longitude" | translate }}</label>
<div class="col-xs-8 input-group">
<input type="number" popover-trigger="focus" placeholder="{{'Longitude' | translate }}"
class="form-control input-md"
ng-model="specimen.decimallongitude" name="decimallongitude"
/>
<span class="input-group-addon" >
<span class="glyphicon glyphicon-question-sign"></span>
</span>
</div>
<dir.inputerrormsg inputdata="formLocalisation.decimallongitude" ></dir.inputerrormsg>
</div>
...
You didn't specified name to your input. Try this:
<form name="studentForm" novalidate>
<input type="text" class="form-control" name ="input" ng-model="formsToBeValidated.firstName" required>
<span studentForm.input.$error.required && studentForm.input.$dirty>First Name is Required</span>
</form>

how to create dynamic form in angularjs?

My error description:
step 1: I am appending template using this directive.
step 2: Now I remove this appended template using this scope function "removeMilestoneDiv".
step 3: After submit my form. But, I can't submitted.
I think I have add template then bind this scope variable. But, i have remove this template then scope variable is can't unbind.
Create directive for add milestone:
app.directive('addMilestone', ['$compile', function ($compile) { // inject $compile service as dependency
return {
restrict: 'A',
link: function (scope, element, attrs) {
// click on the button to add new input field
element.find('a').bind('click', function () {
// I'm using Angular syntax. Using jQuery will have the same effect
// Create input element
// var input = angular.element('<div id="scope.mileStoneId_'+ scope.mileStoneCounter +'" class="form">Milestone - '+scope.mileStoneCounter+'</div>');
var input = angular.element(''+
'<div class="card bg-white" id="mileStoneDiv_'+ scope.mileStoneCounter +'">'+
'<div class="card-header" ng-bind="\'project.ADD_MILESTONE\' | translate"></div>'+
''+
'<div class="card-block m-b-0">'+
'<div compile-template class="form-group">'+
'<label class="col-sm-2 control-label"><span ng-bind="\'project.COMPANY_MILESTONE_ID\' | translate"></span></label>'+
'<div class="col-sm-5">'+
'<input type="text" class="form-control" ng-model="company_milestone_id['+ scope.mileStoneCounter +']" ng-maxlength="100" name="company_milestone_id_'+ scope.mileStoneCounter +'" required>'+
'<div ng-messages="frmProjectAdd[\'company_milestone_id_'+scope.mileStoneCounter+'\'].$error" role="alert" class="help-block has-error">'+
'<span ng-message="required" class="help-block has-error">Company Milestone Id is required.</span>'+
'<span class="help-block has-error" ng-message="maxlength">Maximum 100 characters allowed!</span>'+
'</div>'+
'</div>'+
'</div>'+
'<div compile-template class="form-group">'+
'<label class="col-sm-2 control-label" ng-bind="\'project.MILESTONE_NAME\' | translate"></label>'+
'<div class="col-sm-5">'+
'<input type="text" ng-maxlength="100" class="form-control" ng-model="milestone_name['+ scope.mileStoneCounter +']" name="milestone_name_'+ scope.mileStoneCounter +'" required>'+
'<div ng-messages="frmProjectAdd[\'milestone_name_'+scope.mileStoneCounter+'\'].$error" class="has-error login-error">'+
'<span ng-message="required" class="help-block has-error">Milestone Name is required.</span>'+
'</div>'+
'</div>'+
'</div>'+
'<div compile-special-template class="form-group">'+
'<label class="col-sm-2 control-label" ng-bind="\'project.SELECT_EMPLOYEE\' | translate"></label>'+
'<div class="col-sm-10">'+
'<select style="min-width:250px;" ui-select2 name="select_new_employee_'+scope.mileStoneCounter+'" ng-model="selectEmployee['+ scope.mileStoneCounter +']" data-placeholder="Select Employee" ng-required="true" multiple>'+
'<option ng-repeat="manager in managerList" value="{{manager.id}}">{{manager.username}}</option>'+
'</select>'+
'</div>'+
'<div ng-messages="frmProjectAdd[\'select_new_employee_'+scope.mileStoneCounter+'\'].$error" class="has-error login-error">'+
'<span ng-message="required" class="help-block has-error">Employee is required.</span>'+
'</div>'+
'</div>'+
'</div>');
// Compile the HTML and assign to scope
var compile = $compile(input)(scope);
// Append input to div
$('#milestoneHtml').append(input);
// Increment the counter for the next input to be added
scope.mileStoneCounter++;
});
}
}
}]);
Remove milestone using this function:
$scope.removeMilestoneDiv = function(key, id, flag) {
var confirmVal = confirm("Are you sure you want to delete this Milestone?");
if(confirmVal) {
$('#mileStoneDiv_'+key).remove();
if(flag == 1){
if(id != 0) {
$scope.deletedMilestoneIds.push(id);
}
}
}
},
Create One Array:
$scope.mileStoneCounterNew = [{
'countId':1,
'company_milestone_id':'',
'milestone_name':'',
'milestone_start_date':'',
'milestone_end_date':'',
'milestone_completion_date':'',
'selectEmployee':'',
}];
Create one scope function
$scope.milestoneHtmlAdd = function() {
$scope.mileStoneCounter++;
var counterObj = {countId: $scope.mileStoneCounter };
$scope.mileStoneCounterNew.push(counterObj);
};
My Dynamic HTML
<!-- Add Milestone - Start -->
<div class="row" ng-repeat="(counterKey, counterValue) in mileStoneCounterNew" id="milestone_display_id_{{counterValue.countId}}">
<div class="card bg-white mt50">
<div class="card-header"><span ng-bind="'project.ADD_MILESTONE' | translate"></span></div>
<a ng-if="counterKey > 0" href="javascript:void(0)" class="removebtn glyphicon glyphicon-remove form-control-feedback" ng-click="milestoneDivRemove(counterKey,0,0)"></a>
<div class="card-block m-b">
<!--Milestone sub section-->
<!-- Company Milestone Id -->
<div class="form-group">
<label class="col-sm-2 control-label"><span ng-bind="'project.COMPANY_MILESTONE_ID' | translate"></span></label>
<div class="col-sm-5">
<input type="text" class="form-control" ng-model="counterValue.company_milestone_id" ng-maxlength="100" name="company_milestone_id_{{counterValue.countId}}" required>
<div ng-if="frmProjectAdd.$submitted || frmProjectAdd['company_milestone_id_'+counterValue.countId].$touched" ng-messages="frmProjectAdd['company_milestone_id_'+counterValue.countId].$error" role="alert" class="help-block has-error">
<span ng-message="required" class="help-block has-error">Company Milestone Id is required.</span>
<span class="help-block has-error" ng-message="maxlength">Maximum 100 characters allowed!</span>
</div>
</div>
</div>
<!-- Milestone name -->
<div class="form-group">
<label class="col-sm-2 control-label"><span ng-bind="'project.MILESTONE_NAME' | translate"></span></label>
<div class="col-sm-5">
<input type="text" class="form-control" ng-model="counterValue.milestone_name" ng-maxlength="100" name="milestone_name_{{counterValue.countId}}" required>
<div ng-if="frmProjectAdd.$submitted || frmProjectAdd['milestone_name_'+counterValue.countId].$touched" ng-messages="frmProjectAdd['milestone_name_'+counterValue.countId].$error" role="alert" class="help-block has-error">
<span ng-message="required" class="help-block has-error">Milestone Name is required.</span>
<span class="help-block has-error" ng-message="maxlength">Maximum 100 characters allowed!</span>
</div>
</div>
</div>
<!-- Milestone Start Date -->
<div class="form-group">
<label class="col-sm-2 control-label"><span ng-bind="'project.MILESTONE_START_DATE' | translate"></span></label>
<div class="col-sm-3">
<div class="input-group">
<input name="milestone_start_date_{{counterValue.countId}}" type="text" uib-datepicker-popup="MM/dd/yyyy" ng-model="counterValue.milestone_start_date" is-open="dpOpened['milestone_start_date_'+counterValue.countId]" ng-click="milestone_start_date[counterValue.countId].open = true" max-date="maxDate" datepicker-options="dateOptions" close-text="Close" ng-required="true" class="form-control"
min-date="minDate" ng-change="set_min_milestone_end_Date(milestone_start_date[counterValue.countId])"
disabled>
<span class="input-group-addon" ng-click="open($event,'milestone_start_date_{{counterValue.countId}}')"><i class="fa fa-calendar"></i></span>
</div>
<div ng-if="frmProjectAdd.$submitted || frmProjectAdd['milestone_start_date_'+counterValue.countId].$touched" ng-messages="frmProjectAdd['milestone_start_date_'+counterValue.countId].$error" role="alert" class="help-block has-error">
<span ng-message="required" class="help-block has-error">Milestone Start Date is required.</span>
</div>
</div>
</div>
<!-- Milestone End Date -->
<div class="form-group">
<label class="col-sm-2 control-label"><span ng-bind="'project.MILESTONE_END_DATE' | translate"></span></label>
<div class="col-sm-3">
<div class="input-group">
<input name="milestone_end_date_{{counterValue.countId}}" type="text" uib-datepicker-popup="MM/dd/yyyy" ng-model="counterValue.milestone_end_date" is-open="dpOpened['milestone_end_date_'+counterValue.countId]" ng-click="milestone_end_date[counterValue.countId].open = true" max-date="maxDate" datepicker-options="dateOptions" close-text="Close" ng-required="true" class="form-control"
min-date="milestone_end_minDate" ng-change="set_min_milestone_completed_Date(milestone_end_date[counterValue.countId])"
disabled>
<span class="input-group-addon" ng-click="open($event,'milestone_end_date_{{counterValue.countId}}')"><i class="fa fa-calendar"></i></span>
<div ng-if="frmProjectAdd.$submitted || frmProjectAdd['milestone_end_date_'+counterValue.countId].$touched" ng-messages="frmProjectAdd['milestone_end_date_'+counterValue.countId].$error" role="alert" class="help-block has-error">
<span ng-message="required" class="help-block has-error">Milestone End Date is required.</span>
</div>
</div>
</div>
</div>
<!-- Milestone Completion Date -->
<div class="form-group">
<label class="col-sm-2 control-label"><span ng-bind="'project.MILESTONE_COMPLETION_DATE' | translate"></span></label>
<div class="col-sm-3">
<div class="input-group">
<input type="text" uib-datepicker-popup="MM/dd/yyyy" ng-model="counterValue.milestone_completion_date" is-open="dpOpened['milestone_completion_date_'+counterValue.countId]" ng-click="milestone_completion_date[counterValue.countId].open = true" max-date="maxDate" datepicker-options="dateOptions" close-text="Close" class="form-control"
min-date="milestone_completed_minDate" disabled>
<span class="input-group-addon" ng-click="open($event,'milestone_completion_date_{{counterValue.countId}}')"><i class="fa fa-calendar"></i></span>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label"><span ng-bind="'project.SELECT_EMPLOYEE' | translate"></span></label>
<div class="col-sm-10">
<select name="select_employee_{{counterValue.countId}}" ui-select2 ng-model="counterValue.selectEmployee" data-placeholder="Select Employee" ng-required="true" multiple>
<option ng-repeat="manager in managerList" value="{{manager.id}}">{{manager.username}}</option>
</select>
<div ng-if="frmProjectAdd.$submitted || frmProjectAdd['select_employee_'+counterValue.countId].$touched" ng-messages="frmProjectAdd['select_employee_'+counterValue.countId].$error" role="alert" class="help-block has-error">
<span ng-message="required" class="help-block has-error">Employee is required.</span>
</div>
</div>
</div>
<!-- Milestone sub section -->
</div>
</div>
</div>
<!-- Add Milestone End -->

Chosen dropdown with angular required validation

I am using angular js and the chosen plugin for my dropdowns. I want a validator to show when nothing has been selected in the dropdown. But because chosen replaces the select with some divs and uls, and the select gets hidden, the validation doesn't work. Is there a way I could achieve this with angular? This is my code:
<form class="form-horizontal" role="form" novalidate name="newEmployeeForm">
<div class="form-group">
<label for="username" class="col-sm-3 control-label">User</label>
<div class="col-sm-8">
<select class="form-control" name="user" data-placeholder="Choose a user" ng-model="selectedUser" ng-options="u.fullName for u in users" list="users" chosen required></select>
</div>
<span class="error" data-ng-show="newEmployeeForm.user.$error.required">*</span>
</div>
<div class="form-group">
<label for="email" class="col-sm-3 control-label">Email</label>
<div class="col-sm-8">
<input type="text" class="form-control" id="email" name="email" placeholder="Email" ng-model="employee.email" required>
</div>
<span class="error" data-ng-show="newEmployeeForm.email.$error.required">*</span>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary" ng-click="save()" data-ng-disabled="newEmployeeForm.$invalid">Save changes</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</form>
the directive:
app.directive('chosen', function () {
return {
replace: true,
restrict: 'A',
scope: {
list: "="
},
link: function (scope, element, attr) {
scope.$watch('list', function (newVaue, oldValue) {
if (newVaue == oldValue) {
return;
}
element.chosen();
})
}
}
});

Resources