Duplicate form names in ng-repeat - angularjs

I have a form editQuoteCardForm within an ng-repeat that is repeated multiple times. The form is tied to the editQuoteCard model. When a user clicks the edit button, the form is prepopulated with the correct data for the current model.
The problem I'm having is that I can't validate the form by calling editQuoteCardForm.$valid because there are multiple instances of editQuoteCardForm in the DOM. In fact, if I call $scope.editQuoteCardForm within a debugger session, it returns undefined.
My question is, how can I properly handle the form name within an ng-repeat in such a way that I can validate the form?
Here is the code for my form:
<div ng-repeat="c in quoteCards" style="display:none;" id="{{'edit_quote_card_' + c.id + '_form_container'}}">
<div class="row" id="{{'edit_quote_card_' + c.id + '_form'}}">
<div class="col-lg-12">
<div class="row-scrollable" ng-show="view === 'quote-card'">
<div class="col-lg-12">
<form accept-charset="UTF-8" name="editQuoteCardForm" ng-submit="update({card: editQuoteCard, type: 'quote_card'})" novalidate>
<input name="utf8" type="hidden" value="✓">
<input name="authenticity_token" type="hidden" ng-model="editQuoteCard.token">
<input name="id" type="hidden" ng-model="editQuoteCard.id">
<div class="form-group">
<label>Title</label>
<br style="clear:both;" />
<input type="text" class="form-control" name="title" ng-model="editQuoteCard.title" required>
</div>
<div class="form-group">
<label>Attribution</label>
<br style="clear:both;" />
<input type="text" class="form-control" name="attribution" ng-model="editQuoteCard.attribution">
</div>
<div class="form-group">
<label>Quote</label>
<br style="clear:both;" />
<textarea rows="3" class="form-control" name="quote" ng-model="editQuoteCard.quote" required></textarea>
</div>
<div class="form-group">
<label>Media</label>
<br style="clear:both;" />
<input type="hidden" class="form-control" name="photo" ng-model="editQuoteCard.image">
<input type="hidden" class="form-control" name="video" ng-model="editQuoteCard.video">
<div class="profile-builder attachment">
<div ng-show="editQuoteCard.video" class="content video-content result iframe">
<div class="caption delete-btn" ng-click="editQuoteCard.video = undefined;">
<i class="fa fa-times"></i>
</div>
<iframe ng-if="editQuoteCard.video.media_type === 'Youtube'" ng-src="{{editQuoteCard.video.media_url + '?showinfo=0&autohide=1' | trustAsResourceUrl}}" frameborder="0" id="ytplayer" type="text/html"></iframe>
<iframe ng-if="editQuoteCard.video.media_type === 'Vimeo'" ng-src="{{editQuoteCard.video.media_url + '?badge=0&byline=0&title=0' | trustAsResourceUrl}}" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
<div ng-show="editQuoteCard.image" class="content result">
<div class="delete-btn" ng-click="editQuoteCard.image = undefined;">
<i class="fa fa-times"></i>
</div>
<div class="image-container" ng-style="{'background-image': 'url(' + editQuoteCard.image.image_url + ')'}"></div>
</div>
</div>
</div>
<br style="clear:both;" />
<div class="form-group">
<input class="btn btn-primary" style="float:right;" name="commit" type="submit" value="Update Card" ng-disabled="editQuoteCardForm.$invalid">
<div class="btn btn-default" style="float:right;margin-right:10px;" ng-click="openMediaBrowser({type: c.class, id: c.id, index: $index});" ng-show="!editQuoteCard.image && !editQuoteCard.video">Add Media</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>

You can create name for each form dynamically.
<form accept-charset="UTF-8" name="editQuoteCardForm{{$index}}" ng-submit="update({card: editQuoteCard, type: 'quote_card'})" novalidate>
</form>
So, your forms will be named,
editQuoteCardForm0, editQuoteCardForm1, editQuoteCardForm2 etc.

Related

Ng-click validation is not working

I am beginer in angular js. I am validating a form with some input feild and form is posting on ng-click but validation is not working, validation message are displaying for a white then disappear i have to submit the form after validating. form ng-click should not be called untill the form is valid please help me . Thanks in advance.
<form name="teamForm" novalidate ng-submit="submit(teamForm)" class="formfields">
<div class="col-md-12">
<div class="row">
<div class="col-md-6 col-sm-6">
<div class="form-group">
<label for="lname">First Name:</label>
<input type="text" name="firstname"
ng-model="FirstName" class="form-control custom-form-control"
placeholder="First Name" required="required">
<span class="text-danger"
ng-show="(teamForm.firstname.$dirty || submitted) && teamForm.firstname.$error.required">Required</span>
</div>
</div>
<div class="col-md-6 col-sm-6">
<div class="form-group">
<label for="lname">Last Name:</label>
<input type="text" name="lastname"
ng-model="LastName" class="form-control custom-form-control"
placeholder="Last Name" required="required">
<span class="text-danger"
ng-show="(teamForm.lastname.$dirty || submitted) && teamForm.lastname.$error.required">Required</span>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-sm-6">
<div class="form-group">
<label for="email">Email:</label>
<input type="text" name="email"
ng-model="Email" class="form-control custom-form-control"
ng-pattern="/^[^\s#]+#[^\s#]+\.[^\s#]{2,}$/"
placeholder="Email" required="required">
<span class="text-danger"
ng-show="(teamForm.email.$dirty || submitted) && teamForm.email.$error.required">Required</span>
<span class="text-danger"
ng-show="teamForm.email.$dirty &&teamForm.email.$error.pattern">Please Enter Valid Email</span>
</div>
</div>
<div class="col-md-6 col-sm-6">
<div class="form-group">
<label>Phone Number:</label>
<div class="clearfix"></div>
<input type="text" name="phone"
ng-model="Phone" class="form-control custom-form-control"
placeholder="XXXXXXXXXX" required="required">
<span class="text-danger"
ng-show="(teamForm.phone.$dirty || submitted) && teamForm.phone.$error.required">Required</span>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 col-sm-12">
<div class="form-group">
<label>Message:</label>
<textarea class="form-control rounded-0" rows="5"
name="comment" placeholder="Message"
ng-model="Comment" required="required"></textarea>
<span class="text-danger"
ng-show="(teamForm.comment.$dirty || submitted) && teamForm.comment.$error.required">Required</span>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 col-sm-12">
<div class="form-group">
<label>Upload Resume:</label>
<!--<input type="file" name="ResumePath" id="filehandler" />-->
<input type="file" id="file1" name="file" class="filelabel sr-only" multiple ng-files="getTheFiles($files)" onchange="Checkfiles($(this))" />
<!-- <input type="file" name="file" onchange="angular.element(this).scope().uploadFile(this.files)"/> -->
<label for="file1" class="form-control">
<span><i class="fa fa-file"></i> Drag file here or choose file</span>
</label>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<div vc-recaptcha key="'6Lc860IUAAAAAAyWI9WD8EV4eITu4ODdhuYHdzi8'"
class="grecaptcha" ng-model="respone1"></div>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<button type="button" id="btnSubmit"
ng-click="uploadFiles()" value="Upload"
class="btn btn-green center-block pull-left">
<i class="fa fa-send"></i>{{btnText}}</button>
</div>
</div>
<div class="form-group text-center">
<h5 class="text-success" style="font-weight:bold">{{messagesuccess}}</h5>
<h5 class="text-danger" style="font-weight:bold">{{messageerror}}</h5>
</div>
</div>
</form>
ng-click (or it's vanilla cousin, onclick) do not check form validation. The function for submission needs to be defined at the form level, and then you specify which button acts as the submit button in order to get form behavior.
I see you already have a submit function defined. I assume you want to change that to uploadFiles. And if you want the form to conduct validation, remove the novalidation attribute.
<form name="teamForm" ng-submit="uploadFiles()" class="formfields">
then, for the button you would specify it is the submission button and remove the ng-click.
<button type="submit" id="btnSubmit"
value="Upload"
class="btn btn-green center-block pull-left">
<i class="fa fa-send"></i>{{btnText}}</button>

all the data is gone in the form when i put ng-model angularjs

I want to load data of a selected row in a form in order to update it. I successfully had the data loaded in the form, the but the problem is when I use ng model to save the data all the stuff have been put in the form fields disappear.
<div class="panel-body pan" ng-if="loadedpr">
<form action="#">
<div class="form-body pal">
<div class="row">
<div class="col-md-2">
<div class="form-group">
<label for="refprojet" class="control-label">
Référence Projet *</label>
<input id="refprojet" type="text" value="{{loadedpr.ref_projet}}" class="form-control" disabled ng-model="ref_projet"/>
</div>
</div>
<div class="col-md-5">
<div class="form-group">
<label for="intitulefr" class="control-label">
Intitulé *</label>
<input id="intitulefr" type="text" value="{{loadedpr.intitule_fr}}" class="form-control" ng-model="intitule_fr" />
</div>
</div>
<div class="col-md-5">
<div class="form-group">
<label for="ctot" class="control-label"> Coût Total (TND) *</label>
<input id="ctot" type="text" value="{{loadedpr.cout_total}}" ng-model="cout_total" class="form-control" disabled ng-model="cout_total" />
</div>
</div>
</div>
<div class="form-group">
<label for="description" class="control-label">
Description</label><textarea id="description" rows="3" value="{{loadedpr.description}}" ng-model="description" class="form-control"></textarea>
</div>
<div class="form-actions text-center pal">
<button type="submit" class="btn btn-primary" ng-click="upadateProjet()">Valider</button>
</div>
</div>
</form>
this is the angularjs method:
$scope.updateProjet= function(){
$scope.projet={'ref_projet':$scope.refprojet,'intitule_fr':$scope.intitule_fr,'description':$scope.description,cout_total':$scope.cout_total};
$http.put("/editprojet", $scope.projet)
.success(function(data,status,headers,config){
});
}
rest controller
#RequestMapping(value="/editprojet",method=RequestMethod.PUT)
public Projet editProjet(#RequestBody Projet p) {
return projetMetier.editProjet(p);
}
you are using button type="submit"
it will clear the form use button tag
<button></button>
$scope.updateProjet= function(projData){
$http.put("/editprojet", projData)
.success(function(data,status,headers,config){
}).error(function(data){
console.log(data)
});
}
<div class="panel-body pan" ng-if="loadedpr">
<form action="#">
<div class="form-body pal">
<div class="row">
<div class="col-md-2">
<div class="form-group">
<label for="refprojet" class="control-label">
Référence Projet *</label>
<input id="refprojet" type="text" value="{{loadedpr.ref_projet}}" class="form-control" disabled ng-model="proj.ref_projet"/>
</div>
</div>
<div class="col-md-5">
<div class="form-group">
<label for="intitulefr" class="control-label">
Intitulé *</label>
<input id="intitulefr" type="text" value="{{loadedpr.intitule_fr}}" class="form-control" ng-model="proj.intitule_fr" />
</div>
</div>
<div class="col-md-5">
<div class="form-group">
<label for="ctot" class="control-label"> Coût Total (TND) *</label>
<input id="ctot" type="text" value="{{loadedpr.cout_total}}" ng-model="proj.cout_total" class="form-control" disabled ng-model="proj.cout_total" />
</div>
</div>
</div>
<div class="form-group">
<label for="description" class="control-label">
Description</label><textarea id="description" rows="3" value="{{loadedpr.description}}" ng-model="proj.description" class="form-control"></textarea>
</div>
<div class="form-actions text-center pal">
<button type="button" class="btn btn-primary" ng-click="upadateProjet(proj)">Valider</button>
</div>
</div>
</form>
</div>
have you tried removing the value attribute? this happened to me when I once added DOM forms on the fly, I managed by using jquery to force capture by:
$(this).find('.inputClass').val();
this sort of jequery is already embeded inside Angular so no need to add the the library.

ng-model-option rollback changes on whole form

have a quick question.
I have a form with whole bunch of fields that could be updated from UI.
I found a directive called "ng-model-option" that seems to be handling those kind of issues.
My question is: is it possible to rollback changes on whole form without specifying ng-model-options="{ updateOn: 'submit'}"
on every input fieldin my form?
Or, this directive look on every field and only submit those fields that were modified?
Thank you for your help and explanation in advance!
You could have all of your fields bound to a single object, i.e.
$scope.model = {
foo: '',
bar: '',
etc: ''
};
That way you could store a copy of the model, and reset the bound model at any point you wish.
For example to undo all of the changes after a failed service call:
$scope.submit = function() {
yourService.update(model).then(function(result) {
// handle the success.
}, function(err) {
$scope.model = $scope.originalModel;
});
}
Or maybe reloading the page is an option for you?
$window.location.reload();
i found a solution by using and mapping everything to ng-model-option directive
<form name="EditUserForm" class="col-md-12 form-horizontal top-buffer">
<div class="form-group">
<div class="col-sm-4 text-right">
<label>User Id:</label>
</div>
<div class="col-sm-8">
<input type="text" class="form-control info-textbox" ng-model="user.UserID" ng-disabled="true" />
</div>
</div>
<div class="form-group">
<div class="col-sm-4 text-right">
<label>Department Name:</label>
</div>
<div class="col-sm-8">
<!--<input type="text" class="form-control info-textbox" ng-model="user.Department.DepartmentName" ng-readonly="isReadOnlyMode" />-->
<select class="form-control info-textbox" ng-options="department.DepartmentName for department in departments"
ng-model="selectedDepartment"
ng-readonly="isReadOnlyMode"
ng-model-options="{updateOn: 'submit'}"></select>
</div>
</div>
<div class="form-group">
<div class="col-sm-4 text-right">
<label>First Name:</label>
</div>
<div class="col-sm-8">
<input type="text" class="form-control info-textbox" ng-model="user.FirstName" ng-readonly="isReadOnlyMode" ng-model-options="{updateOn: 'submit'}" />
</div>
</div>
<div class="form-group">
<div class="col-sm-4 text-right">
<label>Last Name:</label>
</div>
<div class="col-sm-8">
<input type="text" class="form-control info-textbox" ng-model="user.LastName" ng-readonly="isReadOnlyMode" ng-model-options="{updateOn: 'submit'}" />
</div>
</div>
<div class="form-group">
<div class="col-sm-4 text-right">
<label>Email:</label>
</div>
<div class="col-sm-8">
<input type="text" class="form-control info-textbox" ng-model="user.Email" ng-readonly="isReadOnlyMode" ng-model-options="{updateOn: 'submit'}" />
</div>
</div>
<div class="form-group">
<div class="col-sm-4 text-right">
<label>Phone:</label>
</div>
<div class="col-sm-8">
<input type="text" class="form-control info-textbox" ng-model="user.Phone" ng-readonly="isReadOnlyMode" ng-model-options="{updateOn: 'submit'}" />
</div>
</div>
<div class="form-group">
<div class="col-sm-4 text-right">
<label>Login:</label>
</div>
<div class="col-sm-8">
<input type="text" class="form-control info-textbox" ng-model="user.LoginName" ng-readonly="isReadOnlyMode" ng-model-options="{updateOn: 'submit'}" />
</div>
</div>
<div class="form-group">
<div class="col-sm-4 text-right">
<label>Password:</label>
</div>
<div class="col-sm-8">
<input type="password" class="form-control info-textbox" ng-model="user.Password" ng-readonly="isReadOnlyMode" ng-model-options="{updateOn: 'submit'}" />
</div>
</div>
<!--Buttons-->
<div class="form-group">
<div class="col-sm-4 text-right">
<button type="button" class="btn btn-primary info-button" name="btnEdit" ng-click="flipBetweenEditMode(isReadOnlyMode)" ng-show="isReadOnlyMode">
<span>Edit</span>
</button>
<button type="button" class="btn btn-primary info-button" name="btnEdit" ng-click="flipBetweenEditMode(isReadOnlyMode)" ng-show="!isReadOnlyMode">
<span>Cancel</span>
</button>
</div>
<div class="col-sm-4 text-left">
<button type="submit" class="btn btn-primary info-button" name="btnSave" ng-click="saveChangesToUser(user, isReadOnlyMode)" ng-show="!isReadOnlyMode">
<span>Save</span>
</button>
</div>
<div class="col-sm-4 text-left">
<div back-button></div>
</div>
</div>
</form>
and then controller
$scope.flipBetweenEditMode = function (isReadOnlyMode) {
if (!isReadOnlyMode) {
$scope.EditUserForm.$rollbackViewValue();
}
console.log(isReadOnlyMode);
$scope.isReadOnlyMode = !isReadOnlyMode;
};
on cancel this will roll back all the changes and restore model at its first stage.

Angularjs IF - ELSE condtion on checkboxes

i am new to Angular js i want to ask i have a case in which i have to return "YES" if the checkbox is checked or true and want to return "NO" when the value is false or unchecked.
actually my data is storing in databse in "Tinyint" 1 or 0 form i want to do when 1 occurs it shows YES any solution for this Any help will be appreciated.
Here is my html
<form class="form-horizontal">
<div class="form-group">
<label class="col-lg-2 control-label">Name</label>
<div class="col-lg-10">
<input type="text" ng-model="rec.Name" placeholder="Name" class="form-control">
</div>
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<div class="checkbox c-checkbox">
<label>
<input type="checkbox" value="" ng-model="rec.isSpecial">
<span class="fa fa-check"></span>is Special</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<div class="checkbox c-checkbox">
<label>
<input type="checkbox" ng-model="rec.isMultiple">
<span class="fa fa-check"></span>Is Multiple</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<button type="button" ng-click="add(rec)" class="btn btn-sm btn-primary">ADD</button>
</div>
</div>
</form>
i need to target checkbox ismultiple and isspecial .
You can use ng-true-value of ng-false-value like this:
<form class="form-horizontal">
<div class="form-group">
<label class="col-lg-2 control-label">Name</label>
<div class="col-lg-10">
<input type="text" ng-model="rec.Name" placeholder="Name" class="form-control">
</div>
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<div class="checkbox c-checkbox">
<label>
<input type="checkbox" ng-model="rec.isSpecial" ng-true-value = "YES" ng-false-value="NO">
<span class="fa fa-check"></span>is Special</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<div class="checkbox c-checkbox">
<label>
<input type="checkbox" ng-model="rec.isMultiple" ng-true-value = "YES" ng-false-value="NO">
<span class="fa fa-check"></span>Is Multiple</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<button type="button" ng-click="add(rec)" class="btn btn-sm btn-primary">ADD</button>
</div>
</div>
</form>

Trigger ng-init manually

I have a profile with a series of cards. Each card has a type (e.g. gallery card, quote card, etc) and the profile can have 1 or more of each type. I'm building a profile editor and want to be able to open an edit form in a modal. Each card has its own type of form with unique inputs, but there is only one form per card type, since we can't know in advance how many cards of each type a profile will have.
For each form, I have a number of ng-init directives to prepopulate the edit form with the current model's attributes. This works great except that if I have more than one card of a type, each card's edit form will have the data from the last card in the set. Is there a way I can trigger the ng-init directives to run again when I open the form (e.g. with an ng-click) so that the user will always see the current model's attributes?
Here is what one of my card forms looks like:
<% if c.class.name == 'QuoteCard' %>
<div class="row-scrollable" ng-show="view === 'quote-card'">
<div class="col-lg-12">
<form accept-charset="UTF-8" name="editQuoteCardForm" ng-submit="update({card: editQuoteCard, type: 'quote_card'})" novalidate>
<input name="utf8" type="hidden" value="✓">
<input name="authenticity_token" type="hidden" ng-model="editQuoteCard.token" ng-init="editQuoteCard.token='<%= form_authenticity_token %>'">
<input name="id" type="hidden" ng-model="editQuoteCard.id" ng-init="editQuoteCard.id='<%= c.id %>'">
<div class="form-group">
<label>Title</label>
<br style="clear:both;" />
<input type="text" class="form-control" name="title" ng-init='editQuoteCard.title = "<%= c.title %>"' ng-model="editQuoteCard.title" required>
</div>
<div class="form-group">
<label>Attribution</label>
<br style="clear:both;" />
<input type="text" class="form-control" name="attribution" ng-init='editQuoteCard.title = "<%= c.attribution %>"' ng-model="editQuoteCard.attribution">
</div>
<div class="form-group">
<label>Quote</label>
<br style="clear:both;" />
<textarea rows="3" class="form-control" name="quote" ng-init='editQuoteCard.title = "<%= c.quote %>"' ng-model="editQuoteCard.quote" required></textarea>
</div>
<div class="form-group">
<label>Media</label>
<br style="clear:both;" />
<input type="hidden" class="form-control" name="photo" ng-model="editQuoteCard.image">
<input type="hidden" class="form-control" name="video" ng-model="editQuoteCard.video">
<%= photo = Photo.find_by(quote_card_id: c.id) %>
<%= video = Video.find_by(quote_card_id: c.id) %>
<div class="profile-builder attachment"
ng-init='<%= "editQuoteCard.image = #{{ image_url: photo.image.url, id: photo.id }.to_json}" unless photo.nil? %>'
ng-init='<%= "editQuoteCard.video = #{{ media_url: video.media_url, media_type: video.media_type, id: video.id }.to_json}" unless video.nil? %>'>
<div ng-show="editQuoteCard.video" class="content video-content result iframe">
<div class="caption delete-btn" ng-click="editQuoteCard.video = undefined;">
<i class="fa fa-times"></i>
</div>
<iframe ng-if="editQuoteCard.video.media_type === 'Youtube'" ng-src="{{editQuoteCard.video.media_url + '?showinfo=0&autohide=1' | trustAsResourceUrl}}" frameborder="0" id="ytplayer" type="text/html"></iframe>
<iframe ng-if="editQuoteCard.video.media_type === 'Vimeo'" ng-src="{{editQuoteCard.video.media_url + '?badge=0&byline=0&title=0' | trustAsResourceUrl}}" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
<div ng-show="editQuoteCard.image" class="content result">
<div class="delete-btn" ng-click="editQuoteCard.image = undefined;">
<i class="fa fa-times"></i>
</div>
<div class="image-container" ng-style="{'background-image': 'url(' + editQuoteCard.image.image_url + ')'}"></div>
</div>
</div>
</div>
<br style="clear:both;" />
<div class="form-group">
<input class="btn btn-primary" style="float:right;" name="commit" type="submit" value="Update Card" ng-disabled="editQuoteCardForm.$invalid">
<div class="btn btn-default" style="float:right;margin-right:10px;" ng-click="openMediaBrowser({type: '<%= c.class %>', id: <%= c.id %>, index: <%= i %>});" ng-show="!editQuoteCard.image && !editQuoteCard.video">Add Media</div>
</div>
</form>
</div>
</div>
<% end %>
And in my controller, I have an edit function that opens the modal with the correct form:
$scope.edit = function(options) {
modal.open({
content: $('#edit_card_' + options.index + '_form'),
elem: $('#edit_card_' + options.index + '_form_container')
})
};

Resources