I'm attempting to use ng-show to show/hide labels if content for that label doesn't exist. So for example, if I entered my phone number into the model, then the "Phone:" label would show with the actual number following. It seems though, that ng-show is evaluating the scope/model, not as true/false on the basis of content/no-content...it just seems to evaluate it as false. How do I write it to evaluate on content, not boolean?
<input type="text" ng-model="data.product.user.phone" />
<div ng-show="data.product.user.phone">
<div>Phone:{{data.product.user.phone}}</div>
</div>
I'm really bad at fiddlin' so forgive the shitty fiddle, that doesn't work at all. http://jsfiddle.net/xVZHL/2/
UPDATE: So the fiddle works. But my source code, does not. The only difference is that we are generating and saving the model on backend/elsewhere so it is not being created and controlled on the main page, but it's just not working...I don't know how to show this in a fiddle. Here is my live code that doesn't work.
<field ng-show="data.product.phone" for="phone" model="data.product.phone" placeholder="Phone" type="field-view"> </field>
field is a directive that has the attributes for, model, and placeholder that it injects into the templates/directives within. data.product.phone, for the purposes of this example, definitely has content in it, but does not show up, even though it should, because in the words of angular content = 'truthy'
Like all HTML attributes, you need the = in ng-show:
<div ng-show="data.product.user.phone">
And correcting the fiddle, it works: http://jsfiddle.net/xVZHL/2/
The field tag is not closed correctly
<field ng-show="data.product.phone" for="phone" model="data.product.phone" placeholder="Phone" type="field-view" </field>
Should be:
<field ng-show="data.product.phone" for="phone" model="data.product.phone" placeholder="Phone" type="field-view"> </field>
UPDATE(ANSWERED):: http://github.com/angular/angular.js/issues/2500 http://groups.google.com/forum/#!msg/angular/FqvC0ciG08w/k7KkyJu7zNoJ Through some more googling, I've found that a directive with an isolate scope, it evaluates it as the isolate scope, so since my scope was already data.product.phone, it was looking at data.product.phone in the scope of data.product.phone, which doesn't exist so it was throwing a wrench in the gears. Putting the ngshow in the template the directive calls works fine, plus less code in the directive calls. Thanks guys!
Related
I am creating a AngularJS app to render forms dynamically from a generic for definition data structure. So the form details (including all validation rules, data types etc) are defined in a database and a single AngularController should "draw" the form.
For background - here is the rough structure of the defiintion:
Form
Sections
Fields
It works fine - but I have a problem when adding attributes to the <input> element on the form based on the definition. So for example, lets say field1requires a min and max length validation, but field 2 does not. This is achieved by adding the ng-minlength and ng-maxlength attributes to the input element for field1 and NOT adding these to the input element for field2.
Some googling sugested that the recently removed ng-attr directive might have been a sollution - but since its removed, I am stuck?
<ng-form name="frmTSFApp">
<uib-tabset>
<uib-tab ng-repeat="aSection in tsf3fd.section track by aSection.ukey"
index="aSection.display_order"
heading="{{aSection.display_label}}">
<ng-form name="frmSection{{aSection.display_order}}">
<div ng-repeat="aField in aSection.fields track by aField.ukey"
class="form-group"
ng-class="getFormClass(frmSection{{aSection.display_order}}[aField.data_name],aField)">
<label class="control-label">{{aField.field_label}}</label>
<input ng-required="{{aField.require_kind == 'R'}}"
type="text"
class="form-control"
ng-model="tsf3fd.model[aField.data_name]"
name="{{aField.data_name}}" />
</ng-form>
</uib-tab>
</uib-tabset>
</ng-form>
The above snippet is what we use to render the form - so the ng-required attribute works nicely, since its always there and its value can be resolved from the expression. For each field we "know" all the validations we need to add (ng-minlength or ng-pattern etc etc) but not sure how to do this?
In psuedo code I would like something like this "inside: the input element:
if (aField.validations.minmax)
{
ng-minlength = "{aField.validations.minmax.min}"
ng-maxlength = "{aField.validations.minmax.max}"
}
Hope my explanation makes sense.
I am starting to doubt my approach - it seems a simpler approach is to render the "literal" form markup externally through something like XSLT from the deffinition data. We have done this and it works fine, but I thought working directly from the data would be so "cool" and would simplify the process.
Anyway - any help would be appreciated.
You can just use:
<input
ng-required="{{aField.require_kind == 'R'}}"
ng-minlength="{{aField.validations.minmax ? aField.validations.minmax.min : '' }}"
ng-maxlength="{{aField.validations.minmax ? aField.validations.minmax.max : '' }}"
type="text"
class="form-control"
ng-model="tsf3fd.model[aField.data_name]"
name="{{aField.data_name}}" />
Setting ng-minlength or ng-maxlength to empty string has the same effect as not setting them.
if(currentAdmin.target =='new')
{
$('#btnDel').hide();
//Not working !!!
$('#inputPassword1').attr("ng-required","true");
$('#inputPassword2').attr("ng-required","true");
}
else
{
$('#btnDel').show();
$('#inputPassword1').attr("ng-required","true");
$('#inputPassword2').attr("ng-required","true");
}
Well, basically I want to place the ng-required based on the condition. I made a trial using the required (without ng) and it does not works as well.
I inspected the element and injected the required and ng-required into the html and it's not works.
This will always be ignored after rendered. I need to do such thing like "Validator, refresh because it's different now"
any clue ?
Even though I myself hate the kind of answer I am about to give, I feel it is appropriate in this situation: This is not the way to write if using angular...
So what should you do?
place the ng-required in the html code and set the value of the attribute to a bound variable that you set depending on your condition.
Example:
index.html
<form ng-controller="formController">
<input type="password" ng-required="isAdmin">
<input type="password" ng-required="!isAdmin">
</form>
app.js
angular.module('app',[]).controller('formController', function($scope){
$scope.isAdmin=false;
if(currentAdmin.target == 'new'){
$scope.isAdmin=true;
}
});
Not complete code, but hopefully you still understand what I mean.
I am looking at using angular for a project at work but I have a question first. We have a single page application that's pretty intricate. We do have a basic model set up but some fields in the model are redundant. If I couldn't reduce the redundancy, what steps could I take in angular so that one form element changes two variables in the model?
I've put together a bare bones jsfiddle of what I'm hoping to do:
<div ng-app>
<input type="text" ng-model="yourName" placeholder="Enter a name here" /><br/>
<span>Hello {{yourName}}!</span><br/>
<span>Hello {{altName}}!</span>
</div>
How could I change this around so that the input would assign it's value to both yourName as well as altName? I've tried what I thought would be obvious such as comma or pipe delimiting the ng-model attribute to no avail. Is it possible?
You could set a $watch on the yourname-Variable within your controller and then change the altName in its callback. Should look like this:
$scope.$watch('yourName', function(){
$scope.altName = $scope.newName;
});
Like in this question, I want to add .error on a form field's parent .control-group when scope.$invalid is true.
However, hardcoding the form name like in ng-class="{ error: formName.fieldModel.$invalid }" means that I can't reuse this in different forms, plus I'd rather not repeat this declaration everywhere.
I figured that a directive that looks something like this could work:
<div class="control-group" error-on="model1, model2">
<input ng-model="model1">
<input ng-model="model2">
</div>
So when either model1 or model2 is not valid, .control-group gets .error added.
My attempt here. Is it possible to access the models from the directive, given the model names?
If there's a better approach, I'd love to hear it too.
I don't think that writing a custom directive is necessery for this use-case as the ng-form directive was created exactly for situations like those. From the directive's documentation:
It is useful to nest forms, for example if the validity of a sub-group
of controls needs to be determined.
Taking your code as an example one would write:
<div class="control-group" ng-class="{ error: myControlGroup1.$invalid }>
<ng-form name="myControlGroup1">
<input ng-model="model1">
<input ng-model="model2">
</ng-form>
</div>
By using this technique you don't need to repeat expressions used in ng-model and can reuse this fragment inside any form.
You can also change the markup in the accepted answer to do without the nesting, since ng-form is also a class directive:
<div class="control-group ng-form" name="controlGroup11" ng-class="{ error: controlGroup1.$invalid }>
<input ng-model="model1">
<input ng-model="model2">
</div>
Final solution Fiddle
Inside your link function, you can get access to the formController. It has all of the controls. So the following will give your directive access to .$valid:
el.controller('form')[attrs.errorOn].$valid
However, I don't know how to watch that for changes. I tried watching attrs.errorOn (i.e., watch the ng-model property), but the watch doesn't trigger unless a valid value is input (because of the way Angular forms work... unless that value is valid, it is not assigned to the scope property set by ng-model.)
Fiddle.
Maybe someone can take this further...
<input type="text" value="{{codes[0].code}}" ng-click="newNumber(0)" />
<input type="text" value="{{codes[1].code}}" ng-click="newNumber({{codes[1].id}})" />
The first ng-click event fires in my controller just fine but the second one does nothing.
I tried concat'ing as well ... is there some other way I should do this?
ng-click
The value of ng-click is already evaluated as an angular expression. As such, you don't need the {{ }}. Read http://docs.angularjs.org/guide/expression for more information. Take a look at the second example, it will help clarify this.
ng-model
Also, ng-model should be used for data-binding. For example, take a look at this jsfiddle: http://jsfiddle.net/bCpW9/8/ and the notes below.
<li ng-repeat="code in codes">
This loops through the codes collection which was defined in the controller. It creates a <li> for each element in the codes collection.
<input ng-model="codes[$index].code" />
Inside each <li>, an <input> for the current code is created. Each input is bound to it's corresponding element in the codes array by setting ng-model to it. For instance, type a new code into the first input field. It automatically updates the corresponding code model with what you typed, as you can see to the right.
I hope that helps.