How to use ng-repeat inside a directive proper way in angularjs - javascript

Plunkr
I made a autofill dropdown using angular custom directive.All is working fine.
But I want to make this directive reusable!!!!
Currently my directive is tightly depended on Id and Name property of selected item.
I want to assign text property(Which I want to bind the text into list items html) and value property(which will be available in my app controller) like textfield="Name" and value-field="Id".
Imagine If my data object does not contain Name or Id property , my
directive would not work.
HTML:
<autofill-dropdown items="searchCurrencies"
textfield="Name" valuefield="Id" selected-data="Id" urllink="/api/SetupCurrency/Autofill?filter=">
</autofill-dropdown>
Template :
<div class="pos_Rel">
<input placeholder="Search Currency e.g. doller,pound,rupee"
type="text" ng-change="SearchTextChange()" ng-model="searchtext"
class="form-control width_full" />
<ul class="currencySearchList" ng-show="IsFocused && items.length">
<li class="autofill" ng-repeat="item in items" ng-click="autoFill(item)">
{{item.Name}}
</li>
</ul>
</div>
So,finally what I want to accomplish , I'm going to bind Name property(or other,depends on what value I set to "text-field" attribute onto my html) to listitems and whenever user select an item, it will give me the selected Id(or other property ,depends on what value I set to "value-field" attribute onto my html).
Plunkr Here
Update:
I think my question not so clear.
I have written same directive 2 times to accomplish and also 2 times same template :(
Please look through my updated plunkr.
Updated Plunkr

I want to say that I am not quit sure if I understood your question in the right way so I try to repeat it.
textfield="Name" valuefield="Id" selected-data="Id"
You want to store the Value of the Property of the selected Item of your custom directive.
The Value should be stored in the Variable provided in the attribute "textfield"
The attribute "valuefield" should define the name of the property of the selected Object
If this is the case you have to get rid of the two-way databinding for your valuefield. Because you only want to provide a String (like "Id" or "Name").
I altered your plunkr again. First of all I made the new scope variables:
scope: {
'items': '=',
'urllink':'#',
'valuefield':'#',
'textfield':'=',
'Id':'=selectedData'
}
Valuefield is now only a text binding. So if you want to change it in the angular way you have to provide a scope variable outside of the directive and a '=' twoway binding inside :D
$scope.autoFill = function (item) {
$scope.IsFocused = false;
$scope.searchtext = item.Name;
$scope.Id = item.Id;
$scope.textfield = item[$scope.valuefield];
}
Also I added the last expression to your autofill function. The name of the property (valuefield) will be written into the textfield variable which is linked with your outside scope (in this case "Name"):
textfield="Name"
If this is not what you asked I am sorry but I am new to stackoverflow and I still can not comment :P
https://plnkr.co/edit/zE1Co4nmIF3ef6d6RSaW?p=preview

Related

Angular typeahead: How to separate label from model?

I am using typeAheads from angular-ui in a UI-grid.
There seem to be a implicit connection between the label in the uib-typeahead and the ng-model.
<input type="text" ng-model="selected" uib-typeahead="country as country.id for country in countrys | filter:$viewValue" typeahead-on-select="onSelect($item, $model, $label)" class="form-control">
In this case the country.id dictates that the value shown in the input after a selection is selected.id. But that is not explicitly defined.
However, if selected does not have a field called id this causes the input to show [Object object].
Can I decouple the model from what is displayed and from the label?
Here is a small plunker. I want the typeahead to list id, but I want the input to display the value of the model.
http://plnkr.co/edit/EnOefFQVcTBoaHxiCc5I?p=preview
EDIT: I changed the plunked to better reflect my problem. If I set ng-model to selected.value I will get a good result in the beginning, but if I change the value I will get a nested JSON in the selected.value
uib-typeahead="country as country.value for country in countrys | filter:$viewValue"
You should use the typeahead like this to have a better understanding of your typeahdead.
However, if you still want to use this with the id, you can use input-formatter. This attribute of typehead defines how your selected object is displayed.
function(ojb) {
return obj.id ? obj.id : obj.value;
}
You will return the id if there is one, otherwise you return the value in the selected object.

What's the significance of `ng-model` attribute in validation in Angularjs?

Why do we need to use ng-model to make sure that validation works. For instance, in this code if I remove ng-model attribute then validation breaks but it works as long as there is ng-model attribute no matter what is the value of attribute is. So what's the significance of ng-model in this case? Why do I have to use though it's value does not make much difference?
The value of ng-model makes all the difference. Not the initial value however, which you are correctly asserting seems to be irrelevant. As soon as you type something into that input box Angular magically assigns the value to the variable assigned to ng-model.
Subsequently, the value of ng-model is what Angular's validation code is validating! The data has to get from your fingers to the code somehow and that's the ng-model.
Let's say you have typed into an input box with ng-model on it: "I am so cool."
<form ng-controller="SuperController">
<input ng-model="somethingAwesome" />
<button ng-click="someAction()">Click me!</button>
</form
Inside your controller you can access that value on the $scope.
function SuperController ($scope) {
$scope.someAction = function () {
console.log($scope.somethingAwesome)
// "I am so cool."
}
}
If you set the value inside your controller.. your input box will display that value.
function SuperController ($scope) {
$scope.somethingAwesome = 'You are so cool!'
}
Angular's validation functions read the value of the stuff on your $scope, which contains the values of items in your view that have the directive ng-model.
https://docs.angularjs.org/api/ng/directive/ngModel

How can I keep ng-model in sync with a select element after ng-options removes the selected option

I have a select element with an ng-model and ng-options on it. ng-options makes the possible selections dynamic however I have noticed that when ng-options updates the options ng-model is not also getting updated. For example if the select element has the value of "foo" selected then the ng-options model is updated and "foo" is no longer an option the selector updates to blank but ng-model still shows "foo" as its value. I would expect that ng-model would update as well to equal null. The only thing I can think of is to add a watch on items but that seems kind of lame. What is the best way to get ng-model to stay in sync with the select element in this scenario?
<div ng-controller="MyCtrl">
<p>Selected Item: {{foo}}</p>
<p>
<label>option</label>
<select ng-model="foo" ng-options="item.val as item.label for item in items">
<option value="">Select Something</option>
</select>
</p>
<button ng-click="remove()">Remove Second Item Option</button>
<p>{{items}}</p>
</div>
Here is the jsfiddle to illustrate the issue. http://jsfiddle.net/dberringer/m2rm8Lh6/2/
Note: I'm aware I could manually update the foo value with the delete method. This method is just to illustrate the issue.
Thanks for your feedback.
Update: I fixed a typo where referred to ng-options as ng-select.
change the button like
<button ng-click="remove(2)">Remove Second Item Option</button>
change the remove function
$scope.remove = function(removeIndex) {
if($scope.foo == removeIndex) {
$scope.foo = null;
}
$scope.items.splice(removeIndex-1,1);
};
here is the Demo Fiddle
Reason is,
ng-change is not going to trigger when,
if the model is changed programmatically and not by a change to the input value, check the Doc here
so u are not changing the select value by changing the select box instead do it using a button (programmatically) so angular will not trigger the change event on the select element and then angular doesn't know model is changed ,this might be the reason.
then what u need to do is change model value manually as $scope.foo = null;
I think angular didn't check that, once the ngOptions value changes, angular didn't do a check to see if the ngModel is exists in ngOptions.
angular.js
line 21371:
self.databound = $attrs.ngModel;
line 21828 - 21840:
return function (scope, element, attr) {
var selectCtrlName = '$selectController',
parent = element.parent(),
selectCtrl = parent.data(selectCtrlName) ||
parent.parent().data(selectCtrlName); // in case we are in optgroup
if (selectCtrl && selectCtrl.databound) {
// For some reason Opera defaults to true and if not overridden this messes up the repeater.
// We don't want the view to drive the initialization of the model anyway.
element.prop('selected', false);
} else {
selectCtrl = nullSelectCtrl;
}
You can see above code checks which option should be selected when generated the options, but i can't find a reverse check when ngOptions got updated.

Angularjs only triggering ng-change on input radio the first time its selected

I have made a simple example using angularjs. This example contains three radio inputs, each of which have to call a function on change (ng-change => console.log). Unfortunately, the function its only triggered the first time any radio input is selected.
HTML:
<div ng-app="myApp" ng-controller="radioGroupController">
<div ng-repeat="value in values">{{value}}
<input type="radio" name="name" ng-model="val" value="{{value}}" ng-change="logChange(val)" />
<hr/>
</div>
</div>
JS:
angular.module('myApp', [])
.controller('radioGroupController', ['$scope', function ($scope) {
$scope.values = ['Option1', 'Option2', 'Option3'];
$scope.logChange = function (newValue) {
console.log('Changed to ' + newValue);
};
}]);
Am I doing something wrong or is this the expected beheaviour?
EDIT: fiddle
Couple of issues/changes:-
1- Change value={{value}} to ng-value="value" because ng-value - Binds the given expression to the value of input[select] or input[radio], so that when the element is selected, the ngModel of that element is set to the bound value.
2- You need to set the selected value on the property on parent scope, you have ng-repeat and you really are setting value of the child scope, so each radio has its own child scope and its value never changes so ng-change is not triggered.
3- You do not need to pass the model value though logChange scope will already have it.
Try:-
In your controller add:-
$scope.selected = {};
and view set the model as a property on selected property of controller scope instead of ng-repeated child scope's val property:-
<input type="radio" name="name" ng-model="selected.val"
ng-value="value" ng-change="logChange()" />
Plnkr
You can change ng-change to ng-click, then it fires every time you actually click on the button.
Here is a JSFiddle.
Depending on what you want to achieve, consider $watch or ng-model for your purpose.
If you bind ng-model to "values" or whatever, you can check which
value it has and work with that. Angulars advantage is exactly this
two-way-databinding without doing anything. No need to call a
function to pass an argument.

Ember Select populated by other Ember Select not updating selection binding

I'm new to Ember.js and I'm trying to figure out how Select views bind their selection to the controller. I have this template:
{{view Ember.Select
contentBinding="content"
selectionBinding="selectedCompany"
optionLabelPath="content.name"}}
{{view Ember.Select
contentBinding="selectedCompany.employees"
selectionBinding="selectedEmployee"
optionLabelPath="content.name"}}
Employee: {{selectedEmployee.name}}
Age: {{selectedEmployee.age}}
I find that the second select does update when selectedCompany changes, but I can't reference the values of name or age in selectedEmployee until I change the second select's value to a different value physically.
How do I make it so that the selectedEmployee is set when the first select changes, such that I can use it's value?
For better clarity, I have my working code here.
Changing content of second selectbox does not actualy change its selection. You have to do it manually, for example by adding following method to controller
onChangeCompany : function() {
if (!this.get('selectedCompany.employees').contains(this.get('selectedEmployee'))) {
this.set('selectedEmployee', this.get('selectedCompany.employees').objectAt(0));
}
}.observes('selectedCompany')
It stil needs some non-null and array-range checking, but does the job - if you select an employee and then change company, employee will change as well.

Categories

Resources