Angular JS pass array of strings into directive - javascript

I have the below directive, which outputs the number and the corresponding string value from the array data.
var app = angular.module("test",[]);
app.controller("Ctrl1",function($scope){
$scope.range = 5;
$scope.data = ['a','b','c','d','e',];
});
app.directive("myDirective", function(){
return {
restrict: "EA",
scope: true,
template: "<div ng-repeat='n in [] | range:range'>{{n + 1}} - {{data[n]}}</div>"
};
})
.filter('range', function() {
return function(input, total) {
total = parseInt(total);
for (var i=0; i<total; i++)
input.push(i);
return input;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test">
<div ng-controller="Ctrl1">
<label>Edit range </label> <input ng-model="range" /><br>
<label>edit data </label> <input ng-model="data" /><br>
<my-directive></my-directive>
</div>
</div>
This runs as expected on load however when the user edits the ng-model="data" the output breaks as it is including the , as an item in the array.
What is the best way to get this working so that when the user updates the data the directive still treat the array like it did initially? (I am happy to either comma seprate items in data or another method such as | if required.)

The better way would be to have a function to push and pop the input data in the array. Something like the following :
HTML :
<input type="text" ng-model="inputdata" ng-click="pushDataInArray(inputdata);"></input>
//And similarly have a function to pop the data from whichever index from the array.
JS:
$scope.pushDataInArray = function(inputdata){
$scope.data.push(inputdata);
};
This would be a better approach IMO.

<input ng-model="data" /> will write the new value into a string an not an array. you need to split the string into an array See http://www.w3schools.com/jsref/jsref_split.asp

Related

Enable/disable input field depending on array length in Angular 1.5

Im new to Angular 1.5. I want have an array and when it is empty, I want to disable an input field. When it's not empty, I want to enable the field. But it's not working as expected. I've put together a simple jsfiddle.
angular.module('demoApp', [])
.controller('MainController', MainController);
function MainController() {
var vm = this;
this.data = ['a', 'b'];
setInterval(function() {
if (vm.data.length === 0) {
vm.data = ['a', 'b'];
} else {
vm.data = [];
}
console.log('vm.data is now ', vm.data);
}, 2000);
}
And
<div ng-app="demoApp" ng-controller="MainController as mainCtrl">
<input type="text" ng-disabled="!data" />
<br />
data is {{ data }}
</div>
I would expect each time the setInterval() method is executed, the HTML would be updated, so the input would cycle between enabled and disabled. But doesn't work and the template isn't outputting the data array.
Since you are using controller instance you need to use its alias mainCtrl, To check if data is empty or not check its length property.
<div ng-app="demoApp" ng-controller="MainController as mainCtrl">
<input type="text" ng-disabled="mainCtrl.data.length == 0" />
<br />
data is {{ mainCtrl.data }}
</div>
Also, You should use $interval instead of setInterval.
Fiddle

Array in Angular scope variable has only one member

I am a beginner to AngularJS and thanks to the Angular community on Stackoverflow which is willing to help a newbie like me, I am learning it very well thanks a lot for that.
Today I would like to add a feature to the exercise I was doing yesterday (which can be found here). I would like to keep a record of the pairs of numbers that the user has typed in and show it as a list of lines. To do that, I introduce an array of number objects. Pressing the button adds the current pair to the array.
Currently, it seems like the array contains only member whatever I do to push new members to it. Can anyone help me find my mistake?
var saApp = angular.module("saApp", []);
saApp.controller('numberController', function($scope) {
$scope.numbers = [];
$scope.number = {
number1: 0,
number2: 0,
sumIt: function() {
var numberObject;
numberObject = $scope.number;
return parseInt(numberObject.number1) + parseInt(numberObject.number2);
}
};
$scope.pushIt = function() {
if ($scope.number !== undefined)
$scope.numbers.push($scope.number);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="saApp" ng-controller="numberController">
<input type="text" ng-model="number.number1" placeholder="Enter a number here">
<input type="text" ng-model="number.number2" placeholder="Enter another number here">
<br />{{number.number1}} + {{number.number2}} = {{number.sumIt()}}
<br />
<br />
<button ng-click="pushIt()">Push</button>
<div ng-repeat="number in numbers">
{{number.number1}} + {{number.number2}} = {{number.sumIt()}}
<br />
</div>
</div>
One change in your current code just clone the $scope.number before pushing into the $scope.numbers array.
$scope. pushIt = function() {
if ($scope.number !== undefined)
$scope.numbers.push(angular.copy($scope.number));
}
Why we should clone before pushing.
The $scope.number object is the same always thus all of the elements in the array will have the same $$hashkey and you will get this error
So you should clone or copy the object before pushing, so that the array has new element objects in it.
Working code here
Use object having keys as input fields to be pushed in ng-repeat. Every repeated object will have his own scope and will update biding values accordingly.
Try this:
var saApp = angular.module("saApp", []);
saApp.controller('numberController', function($scope) {
$scope.numbers = [];
$scope.pushIt = function() {
var obj = {
number1: 0,
number2: 0,
sumIt: function() {
return parseInt(this.number1) + parseInt(this.number2);
}
}
$scope.numbers.push(obj);
}
$scope.pushIt();
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="saApp" ng-controller="numberController">
<button ng-click="pushIt()">Push</button>
<div ng-repeat="number in numbers">
<input type="text" ng-model="number.number1" placeholder="Enter a number here">
<input type="text" ng-model="number.number2" placeholder="Enter another number here">{{number.number1}} + {{number.number2}} = {{number.sumIt()}}
<br />
</div>
</div>
Fiddle here
$scope.pushIt = function() {
if ($scope.number)
$scope.numbers.push($scope.number);
}
Replace your pushIt function by this Code

AngularJs ng-model substr

How can I set input value with without first letter of ng-model. I do not want to change model value itself. Just content of input to be without first letter.
<input type="text" ng-model="myVal" >
and js
$scope.myVal = 'Hello';
Wanted result: ello
Assuming you don't want two way data-bindin you can use value instead of ng-model
<input type="text" value="{{myVal.substr(1)}}" >
If you do want two way databinding, using substr on a model statement doesn't make sense.
Have 2 models and use ng-change in your input to update the original model as you change your input model.
angular.module('myApp',[]).filter('myFilter',function(){
return function(input){
input = input.substring(1,input.length);
return input;
};
})
.controller('myController',function($scope,$filter){
$scope.myValObj = "Hello";
$scope.myValObj2 = $filter('myFilter')($scope.myValObj);
$scope.updateOriginal = function(){
$scope.myValObj = $scope.myValObj[0] + $scope.myValObj2;
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myController">
<input type="text" ng-model="myValObj2" ng-change="updateOriginal()"/>
<br>
Original Model: {{myValObj}}
<br>
Model For Input: {{myValObj2}}
</div>

Angularjs ng-required call function

It is possible make the required value dependet of some funcion?
Something like this? I want to do this because I want to change the required attribute to some form inputs...
HTML:
Name: <input type="text" ng-model="user.name" ng-required="isRequired('name')" />
Age: <input type="text" ng-model="user.age" ng-required="isRequired('age')" />
JS:
$scope.isRequired(fieldName){
$scope.requiredFields = [];
//$scope.requiredFields = STUFF FROM SOME REST SERVICE
for (i in requiredFields) {
if (requiredFields[i] == fieldName){
return true;
}
}
return false;
}
Updated Answer:
So based on your updated OP, what you want is certainly doable. The problem with what you were trying to do is that ng-required has no ability to execute a function, it only reads a boolean. But we can dynamically create variables based on data from the server to automatically set fields to required:
Updated Plunker
<form>
Name: <input type="text" ng-model="user.test" ng-required="name" /><br/>
<input type="text" ng-model="user.name" ng-required="age" />
<br/>
<button type="submit">Submit</button>
</form>
Note that I put a $scope property for each input in the ng-required attribute. Now we can dynamically create that $scope property and set it to true if our data says we need to:
$scope.isRequired = function(){
$scope.requiredFields = [];
$http.get('fields.json')
.success(function(data){
$scope.requiredFields = angular.fromJson(data);
console.log($scope.requiredFields.required)
for (i = 0; i < $scope.requiredFields.required.length; i++) {
$scope[$scope.requiredFields.required[i]] = true
}
console.log($scope[$scope.requiredFields.required[0]]);
})
//$scope.requiredFields = STUFF FROM SOME REST SERVICE
}
$scope.isRequired()
So it is iterating over an array of required fields received from the server, and then dynamically creating a $scope property for each one that is required, and setting it to true. Any field that has that $scope property in it's ng-required will be required now. Anything not dynamically created will just return false, and ng-required doesn't trigger.
Original answer:
Plunker
As Pratik mentioned, ng-required only accepts a Boolean value, but we can toggle the value of that with a function.
HTML
<form>
Name: <input type="text" ng-model="user.name" ng-required="isRequired" />
<br/><button ng-click="toggle()">Required: {{isRequired}}</button>
<button type="submit">Submit</button>
</form>
code:
$scope.isRequired = true;
$scope.toggle = function() {
$scope.isRequired = !$scope.isRequired;
}
I know this is a couple of years old and so AngularJS may have changed, but the accepted answer as it stands today isn't correct. You can very easily execute a function within ng-required, as it takes an expression, which can be a function. For example:
index.html
<div ng-controller="ExampleController" class="expressions">
Expression:
<input type='text' ng-model="expr" size="80"/>
<button ng-click="addExp(expr)">Evaluate</button>
<ul>
<li ng-repeat="expr in exprs track by $index">
[ X ]
<code>{{expr}}</code> => <span ng-bind="$parent.$eval(expr)"></span>
</li>
</ul>
</div>
script.js
angular.module('expressionExample', [])
.controller('ExampleController', ['$scope', function($scope) {
var exprs = $scope.exprs = [];
$scope.expr = '3*10|currency';
$scope.addExp = function(expr) {
exprs.push(expr);
};
$scope.removeExp = function(index) {
exprs.splice(index, 1);
};
}]);
In script.js, a function addExp is defined and added to the scope, and then it's called in the ng-click directive of the a tag, which also takes an expression as its argument.
This code is taken directly from the AngularJS documentation on expressions. It doesn't use ng-require directly, but any directive that takes an expression will work the same. I have used the same syntax to use a function for ng-require.

Dynamically add filter options in angularjs

Hello I have a small project in which I want to have perform search from multiple dynamically added text fields.
This is how I add the search fields:
<div class="form-group" ng-repeat="choice in choices">
<button ng-show="showAddChoice(choice)" ng-click="addNewChoice()">Add another choice</button>
<input type="text" ng-model="choice.name" name="" placeholder="Search criteria">
</div>
And later I have a table with ng-repeat and here is that part:
<tr ng-repeat="todo in todos | filter: {filter from all fields}">
.......
</tr>
What I want to do is to have the contents filtered with all dynamically added search fields.
You'll have to create your own filter to handle that. I've gone ahead and gotten you started.
$scope.myFilter = function(input){
for(var key in input){
for(var x = 0; x < $scope.choices.length; x++){
if(input[key] == $scope.choices[x].name){
return true;
}
}
}
return false;
}
Here is the jsFiddle of the output: http://jsfiddle.net/wsPrv/
Rather than using the filter, do the filtering in the controller yourself. Here is the updated fiddle with the solution. In the first textbox, replace choice1 with "some" and you will see the todo with text "Some stuff" being displayed.
See the relevant part below. For details, see the fiddle.
$scope.$watch('choices', function(newValue) {
$scope.DisplayedTodos = [];
// Filter items here and push to DisplayedTodos. Use DisplayedTodos to display todos
}, true);

Categories