AngularJS SELECT doesn't validate properly - javascript

This is an AngularJS application (1.2.16). I browse to a dialog to edit some item. One of the controls is a multi-SELECT with the following visible values:
incident
work order
These visible values correspond to the following data values:
INCIDENT
WORK_ORDER
This is done through using the ng-options=" ... as ... for ... in ... " pattern, using an enumeration:
var FlexFieldSubjectTypeEnum = {
INCIDENT:{name:"INCIDENT", description:"incident"},
WORK_ORDER:{name:"WORK_ORDER", description:"work order"}
}
If have a form pretty much as follows:
<form ng-submit="save(formName)" name="formName" class="form-horizontal">
...
<div class="control-group">
<label class="control-label">Subject type:</label>
<div class="controls">
<select name="subjectType"
ng-options="type.name as type.description for type in getEnumAsArray('FlexFieldSubjectTypeEnum') | orderBy:'name'"
ng-model="entity.subjectType"
required></select>
</div>
</div>
Now, if the dialog loads the item ($scope.entity) from the backend and entity.subjectType is set to the first item in the list, the form validation marks it as unset. I have many other dialogs with similar constructs and have not seen this problem anywhere else.
If the item returned from the backend points to the second item (WORK_ORDER), this is nicely represented in the SELECT ("work order") and there is no validation error.
The problem does exist equally when using required or ng-required="true".
The problem does not exist if I remove the required attribute, but then the field also suddenly becomes optional, which is not what I wanted.
Your help much appreciated!

Almost a month later, with meanwhile an upgrade from Bootstrap v2.2.2 to v3.1.1 the problem disappeared.

Related

PHP/Javascript: Where to specify components of a drop down list?

I have recently been trying to alter someone else's code however am a complete beginner when it comes to PHP/Javascript. I want to add an extra option to a drop down menu that specifies the Read/Write nature of an object. Currently the only options are 'R' and 'W' however I would like to add an R/W option for Read/Write. To the best of my knowledge I believe the drop down list itself is instantiated here however please correct me if I'm wrong.
<div class="form-group">
<label class="col-sm-3 control-label">Read/Write:</label>
<div class="col-sm-3">
<select class="form-control" ng-options="item for item in readWrite" ng-model="singleRegister.RW" ng-change="modbusChange(modbusDetailsEdit)"> </select>
</div>
</div>
Where should I be looking in the code for the items in the list? I found this in a javascript file that seemed like what i was looking for:
$scope.readWrite=['R','W'];
However when i altered it to look as below nothing changed in the code
$scope.readWrite=['R','W','R/W'];
Any help would be much appreciated.
EDIT: This is the list in question FWIW...

Select empties after clicking outside AngularJS/bootstrap

I'm new to AngularJS and currently i have a problem with a select.
I'm editing existing user info, and when it comes to choose a profile (perfil) or enterprise (empresa) it starts blank, that is not a problem, the problem is that if I click outside any input, the selected option vanishes FROM THE VIEW (i've checked and the data did bind).
Example:
The code it's here:
/*This is how i obtain the profiles from a table, this returns an array of objects which contains "codigo","descripcion","idPerfil"*/
function listaperfiles(){
var listaperf= portalServicios.listaperfiles(mntusuarioCtrl.id).$promise;
listaperf.then(function(respuesta){
mntusuarioCtrl.perfiles=respuesta;
});
listaperf.catch(function(respuesta){
$log.error("Perfiles Error");
$log.error(respuesta);
});
}
/*This function obtains a list of registered users from a table, this contains "nombre","apellidos","codigo","clave","idUsuario","tblPerfil","tblEmpresa", "estatus","email", "seleccionado" is just the user selected fomr that list that is going to be modified or deleted*/
function listaUsuarios(data){
var listausr = ssmeServicios.obtenusuarios(data).$promise;
listausr.then(function (respuesta){
$log.info(respuesta);
mntusuarioCtrl.usuarios=respuesta;
});
listausr.catch(function(respuesta){
$log.error(respuesta);
})
}
<div class="form-group">
<label for="perfil" class="col-sm-3 control-label" style="padding-right: 10px">Perfil:</label>
<div class="col-sm-9">
<select required="true"
id="perfil"
ng-model="mntusuarioCtrl.seleccionado.tblPerfil"
ng-options="opcion.descripcion for opcion in mntusuarioCtrl.perfiles">
<option value="" select hidden/>
</select>
</div>
</div>
it's just a minor nuisance but it has been bothering me!
If needed i can provide more info about the code or anything.
Thank you for your time!.
Here is a plunker with a select example, modified with a similar structure to your code:
http://plnkr.co/edit/sOqtxVz2utHUXhw0hOQd
Hope it helps! If not, please explain a little bit better your solution. A plunker could help a lot!
EDIT:
Now with your plunker I can see your error. Here is a forked plunker working good: http://plnkr.co/edit/sm1DhanxJpLJ4Yrkhucx?p=preview
Angular looks for object equality to bind it with your syntax and 2 objects are equal only if they point to the same reference. So it couldn't load the selected value. However, using track by solves this issue.

Don't submit form if inputs are empty

I have two sets of data: "heat" and "cold", which are retrieved from another provider. This data is quite unorganized and I have removed lots of stuff in the code just to show the essential part of my problem. "Heat" and "cold" both contain properties that the user has to fill in. This property however is dynamic and the amount of properties is not fixed (hence it is in a loop as shown in the code).
My goal is to hide/disable the submit button, which is located all the way down, whenever one single input field in the list in either sets of data is empty. This should also preferably work on Internet Explorer 9, where the 'required' tag is not supported.
I have tried:
Adding the required tag. This unfortunately does not work in IE9 and I have some issues even in Google Chrome because it is still submitting my form. (I added the form tags too)
Adding Ng-show on the submit form. I checked whether the userInput is empty, but this still does not work.
Now you may ask, why wouldn't I just check in my controller whether these properties are empty in my submit method? While it is a good point, I can not access this dynamic data very easily in my controller. Hence, I need a solution that will hopefully fix this problem with no/mimimal effort in the controller.
Code:
<!--Start wrapper!-->
<div class="wrapper">
<div ng-repeat="(code, program) in data.old.heat">
<div class="row" ng-repeat="(componentId, component) in program">
<div class="inputForm">
<!--This field may not be left empty!-->
<input type="text" class="form" ng-model="component.userInput">
</div>
</div>
</div>
<div ng-repeat="(code, program) in data.old.cold">
<div class="row" ng-repeat="(componentId, component) in program">
<div class="inputForm">
<!--This field may not be left empty!-->
<input type="text" class="form" ng-model="component.userInput">
</div>
</div>
</div>
</div>
<!--End of wrapper !-->
<div class="submitPanel">
<button ng-click="submit()">Submit</button>
</div>
Here ya go : https://jsfiddle.net/DIRTY_SMITH/zxbe5rt0/
function validate(){
var text1 = document.getElementById('text').value;
if (text1.length > 0){
alert("went through");
return true;
}
alert("did not go through");
return false;
}
Not specific to angular, but you could check if it has characters via jQuery.
Html
<div class="submitPanel">
<button class="submit-btn" ng-click="submit()">Submit</button>
</div>
jQuery
$('#form input').blur(function()
{
if( $(this).val().length === 0 ) {
$(this).parents('.submit-btn').addClass('hide');
}
});
CSS
.hide{
display:none;
}
I have two options for you, but they both include ng-disabled (https://docs.angularjs.org/api/ng/directive/ngDisabled).
You can put this attribute on the button and you can either call a function on the scope in that attribute and check if all values are given.
So like: ng-disabled="checkInputs()".
Or
You wrap a form around all your inputs, give the form a name like name=form and set the required attribute on all inputs. (EDIT: you could use ng-required="true" for IE9.)
Then you could say ng-disabled="!form.$valid".

How to combine ng-message messages

I am new to AngularJS but I have searched extensively and could not find a working answer to this question, maybe its just not possible the way I have it in mind.
What I would like is to be able to combine error conditions so that I can use more generic error messages in the ng-messages module. This saves us a lot of time maintaining texts as our application is multi-lingual. In my example it would be great to combine minlength, maxlength, and pattern and have it reference 1 generic message. The only way I have gotten it to work is for a separate ng-message for each type and then reuse the error text which seems redundant to me. Hopefully it's something short I am missing like not understanding when/how to use , or ||.
<form id="myFormId" name="myForm" novalidate>
<input name="sText" ng-model="someText"
type="text"
required
ng-minlength="8" minlength="8"
ng-maxlength="8" maxlength="8"
ng-pattern="/^[a-zA-Z0-9]{8,8}$/" pattern="/^[a-zA-Z0-9]{8,8}$/">
<div ng-messages="myForm.sText.$error" role="alert">
Error message:
<div ng-message="required">Required text missing</div>
<div ng-message="minlength || maxlength || pattern">Not right length or bad pattern - Why does this not work? I have also tried using comma , instead of || </div>
<div ng-message="minlength">Too short - this does work but does not change even if this is removed</div>
</div>
</form>
I have created this simple Plunk to illustrate what I am trying to do:
EDIT 1
I do realize I could use a single regex pattern expression but the above validations is strictly to reproduce the issue and show an example. I have other validations I would like to combine that could not be expressed with a single pattern.
ng-messages will show error message inside ng-messages directive element, but that has limitation that you could only display single error ng-message inside the ng-messages div.
So if you wanted to show multiple ng-message inside ng-messages directive you need to add ng-messages-multiple attribute on ng-messages directive element.
Docs Link
Markup
<div ng-messages="myForm.sText.$error" role="alert" ng-messages-multiple>
Error message:
<div ng-message="required">
Required text missing
</div>
<div ng-message="minlength, maxlength, pattern">
Not right length or bad pattern - Why does this not work? I have also tried using comma , instead of ||(OR)
</div>
<div ng-message="minlength">
Too short - this does work but does not change even if this is removed
</div>
</div>
Working Plunkr
Update
After angular document updation I came to know that ng-messages doesn't support to show multiple ng-message error inside ng-messages, for solving this problem we should have ng-messages-multiple attribute on ng-messages element.
From Docs
By default, ngMessages will only display one error at a time. However, if you wish to display all messages then the ng-messages-multiple attribute flag can be used on the element containing the ngMessages directive to make this happen.
Markup
<div ng-messages="myForm.sText.$error" role="alert" ng-messages-multiple>
Error message:
<div ng-message="required">
Required text missing
</div>
<div ng-message="minlength, maxlength, pattern">
Not right length or bad pattern - Why does this not work? I have also tried using comma , instead of ||(OR)
</div>
<div ng-message="minlength">
Too short - this does work but does not change even if this is removed
</div>
</div>
Working Plunkr
In Angular 1.4 you can specify multiple errors for a ng-message:
<div ng-message="minlength, maxlength">
Your email must be between 5 and 100 characters long
</div>
See documentation
Inorder to make your ng-message more generic you can keep all your error messages at one place and use it when required. You could do this using ng-message-include.
Have a look at : Reusing and Overriding Error Messages
http://www.yearofmoo.com/2014/05/how-to-use-ngmessages-in-angularjs.html#reusing-and-overriding-error-messages.
I think you will like to implement this.

Why do two forms appear?

I am using jQuery and bootstrap to give drop-down search suggestions.Following is the html code.But when I type something in the search form and then clear the form.Two forms apears as in the picture.Why? I am new to jQuery. Thanks for any help.
<div class="container">
<div class="row">
<div class="span6 offset3">
<form class="form-search">
<input type="text" id="month" name="month" class="input-medium search-query">
<button type="submit" class="btn">Search</button>
<div id="suggestions">
</div>
</form>
</div>
</div>
</div>
<script>
jQuery("#month").keyup(function(){
ajax('search', ['month'], 'suggestions')});
</script>
EDIT:
I am using web2py framwork.This is the search function's code:
def search():
if not request.vars.month: return dict()
month_start = request.vars.month
selected=complete('piracyfinder',month_start) #this line get the search results
return DIV(*[DIV(k['title'],
_onclick="jQuery('#month').val('%s')" % k['title'],
_onmouseover="this.style.backgroundColor='lightblue'",
_onmouseout="this.style.backgroundColor='white'"
) for k in selected])
It appears you are using the same function (i.e., search()) to fill in the suggestions as well as to create the form (though that function doesn't process the form when submitted). According to the logic, when request.vars.month is either empty or does not exist, the function returns an empty dict. This will result in the associated view (i.e., /views/[controller name]/search.html) being executed and returned. Presumably the search.html view contains the HTML code shown above. So, when you clear the input box, the keyup handler is triggered and sends an empty month variable, which results in a new copy of the form being sent back and inserted in the "suggestions" div. You can avoid this problem by checking whether request.vars.month exists:
if not request.vars.month:
return '' if 'month' in request.vars else dict()
A better approach might simply be to use different functions for the search form and the suggestions given that they do completely different things and don't share any code.
if not request.vars.month also applies to the month var existing but being empty. Therefore, it's returning the form.
You need to do one of these:
Have your "suggestions" code be in a different page/file
Add a isAJAX variable to the request (or some other way to identify AJAX requests)
Check if the variable exists, rather than checking if it is falsy.

Categories