I would like to know if it is possible with AngularJs to render an array element by using another scrop variable as the index like :
{{array[{{index}}]}}.
For example I am trying to achieve this (note the nested {{}} ) :
<ion-item collection-repeat="item in prodataSelect" collection-item-height="52">
<img class="imageoptionsbrand" src={{imagesUrls[{{item.brand | lowercase | nospace}}+'.png']}} />
</ion-item>
Both prodataSelect and imagesUrls are in the scope of the view in controller.js :
angular.module('SnowBoard.controllers', ['SnowBoard.services'])
.controller('ComputeCtrl', function($scope, $ionicPopup, $timeout, sessionService) {
$scope.prodataSelect = [];
prodata = sessionService.get('prodata');
$scope.prodataSelect = prodata;
$scope.imagesUrls = sessionService.get('imagesUrls');
})
The array imagesUrls is as follows:
Object {
byrne.png: "./img/brands/byrne.png"
byrne.pngtype: "brand"
owenwright.png: "./img/pros/owenwright.png"
owenwright.pngtype: "pro"
BX2.png: "./img/boards/BX2.png"
BX2.pngtype: "board"
BlakBox2.jpg: "./img/boards/BlakBox2.jpg"
BlakBox2.jpgtype: "board"
CI-girabbit.png: "./img/boards/CI-girabbit.png"
CI-girabbit.pngtype: "board"
...
Thanks
Yes you can.
Try removing the curly braces # item and maybe also remove the .png or add it after the retrieved image name?
<img class="imageoptionsbrand" ng-src={{imagesUrls[{{item.brand | lowercase | nospace}}]+'.png']}} />
to
<img class="imageoptionsbrand" ng-src="{{imagesUrls[(item.brand | lowercase | nospace) + '.png']}}"] />
To show you that it is possible check this quick example that I've put together
plunkr
Related
I've build a simple component that allows passing a filter as a parameter, and I'm trying to use that parameter in the component view, but I don't know how. It gets passed as a string so it's treated as a string in the component view and thus not working.
Basically it looks something like this:
<number-compare value="some.value" filter="currency"/>
And in the component view:
<span> {{ numCompCtrl.value | numCompCtrl.value.filter }} </span>
But that doesn't work because it gets interpreted as {{ 10 | "currency" }}
I've tried to handle it in the controller instead, and apply the filter there but it gets really messy when the filter needs multiple parameters so the easiest thing by far would be if I could get the simple way working.
Is it possible?
Actually, I just discovered that I had already solved this previously with another filter as a workaround 🙈
(function() {
'use strict';
angular
.module('core')
.filter('dynamic', dynamic);
dynamic.$inject = ['$interpolate'];
function dynamic($interpolate) {
return function(value, name) {
if (!name) {
return value;
}
var result = $interpolate('{{ value | ' + name + ' }}');
return result({ value: value });
};
}
})();
And used like this:
{{ numCompCtrl.value | dynamic: numCompCtrl.value.filter }}
I'm trying to filter data based on the select and input fields. Here is part of my code:
<select ng-change="students.changeValue(changeFilter)" ng-model="changeFilter">
<option ng-selected="true" value="name">Name</option>
<option value="age">Age</option>
</select>
<input ng-model="searchPhrase" />
name and age are example keys that I have. Here is my data generator structure:
<div ng-class="{breakLine: $index % 3 === 0}"
class="student-item col-md-4"
ng-repeat="s in students.studentsList | filter:{searchFilter: searchPhrase}">
The searchFilter is supposed to be a key that is set from a variable but it doesn't work. If I make there something like: filter:{name: searchPhrase} then it works because I have such keys in my data structures.
Here is a part of the controller:
.controller('StudentsListCtrl', ['$scope', function($scope) {
$scope.searchFilter = '';
this.changeValue = function(val) {
console.log(val); ---> gives key or age on change
$scope.searchFilter = val;
}
So when I manually write e.g.: | filter:{name: searchPhrase} then it works. But when I pass 'name' (i.e. the key) in a variable like: | filter:{searchFilter: searchPhrase} then it's broken...
How can I fix this?
You should use the last option described in filter documentation for the expression:
function(value, index, array): A predicate function can be used to write arbitrary filters. The function is called for each element of the array, with the element, its index, and the entire array itself as arguments.
In the controller, you define the predicate, e.g.
$scope.personFilter = function(person) {
// return true if this person should be displayed
// according to the defined filter
}
and use it in the ng-repeat filter, e.g.
<ul>
<li ng-repeat="p in persons | filter:personFilter">{{p.name}} ({{p.age}})</li>
</ul>
See the plunker for a demo. Note I choose age as a string to simplify the predicate function. You can refine it according to your needs.
Write a function in your $scope to generate the object that is passed to the filter:
$scope.getFilterObject = function() {
var filterObject = {};
filterObject[$scope.searchFilter] = $scope.searchPhrase;
return filterObject;
}
Use it as the argument in the filter:
ng-repeat="s in students.studentsList | filter:getFilterObject()"
I'm currently making a front-end with Angular.
I have a JSON file like following:
{
"groups": [
group1: {
"part":1
},
group2: {
"part":2
}
]
}
And I have lists like following:
<li ng-class="{active: section >= {{group.number}}}" ng-bind="group.title" ng-repeat="group in groups" ></li>
Let's say there are 100 groups in my JSON file. If I want to only show groups with "part":1, how do I add this filter in ng-repeat?
You can pass an object to filter with the key/value you want to filter on:
ng-repeat="group in groups | filter:{part:1}"
try this
ng-repeat="group in groups | filter:{'part': 1}:true"
from official documentation
In HTML Template Binding
{{ filter_expression | filter : expression :
comparator}}
for comparator value if its true
true: A shorthand for function(actual, expected) { return
angular.equals(actual, expected)}. This is essentially strict
comparison of expected and actual.
this gives you the exact match
Consider also passing a function rather than Object into filter (which may work this time, but not all things are easily expressible in a readable fashion directly in the view):
ng-repeat="group in groups | filter:functionOnScope"
The | pipe operates on the thing to the left groups, so filter is a function whose first argument receives groups and whose subsequent arguments appear after the :. You could visualize a | b:c:d | e as e(b(a,c,d)) - once I realized that I used filters more for simple things.
So the second argument filter receives is a predicate (function that takes in something and returns true or false to operate on each element - like a SQL WHERE clause) inside groups. Filters are super useful - if you have quick logic or transformations you want to do in the view (and you don't need to test it) then they can make your controllers and directives more succinct. (So instead of ng-if="collection[collection.length - 1].length > 0" you could write ng-if="collection | last | some", which is much more readable.)
If you have complicated logic, it may be better to put in a controller or directive instead of the view (this is also easier to unit test that way if you care about it) - if it's in the view you need something like PhantomJS at a minimum to emulate the DOM. Assuming you bound some dynamicallySelectedPart on the $scope to 1, 2, etc. maybe as an ng-model on a <select /> so the user can select it, then you can just write this to keep it dynamically up-to-date.
$scope.functionOnScope = function (elementInGroups) {
// Maybe do a check like:
// if ($scope.dynamicallySelectedPart === elementInGroups.part) {
return true;
// }
// Some other logic...
return false;
};
Your JSON looks malformed in that you have an array with key-value pairs.
Below is some code that should work. I am using the Controller ViewAs syntax.
HTML
<div ng-app="MyApp">
<div ng-controller="MyController as me">
{{me.greeting}}
<ul>
<li ng-repeat="group in me.groups | filter:{'part': 1}:true">
{{group}}
</li>
</ul>
</div>
JS
var myApp = angular.module('MyApp',[]);
myApp.controller('MyController', function() {
this.greeting = 'Hola!';
this.groups = [ {id: 'group1', "part":1 }, {id: 'group2', "part":2 } ];
});
Code Pen Here
All:
I wonder how can I set a OR operator on a HTML string in Angualar Template, something like:
<div>{{value || <h6>No Header for now.</h6>}}</div>
The logic is if value is a string but not undefined, we show the value text, otherwise we show a error "No Header for Now" wrapped up by <h6>.
I do not know why this expression can not be correctly interpreted?
Thanks
This can be solved with ng-if:
<div ng-if="value">value</div>
<div ng-if="!value"><h6>No Header for now.</h6></div>
You can add specific attributes (e.g. class) and/or directives (e.g. ng-click) on each <div>.
The problem with using a single element is that you have to repeat your condition several times:
<div ng-class="{ value: 'class1', !value: 'class2' }"
ng-click="value ? action1() : action2()"
ng-bind-html="value || html">
</div>
You have to put a string, not an expression: <h6>No Header for now.</h6> is an invalid js expression. '<h6>No Header for now.</h6>' is a string and can be displayed in the {{ }}.
<div>{{value || '<h6>No Header for now.</h6>' }}</div>
or
<div>{{value != null ? value : '<h6>No Header for now.</h6>' }}</div>
I'm convinced the 2nd works.
EDIT:
If you want to add html code in the {{ }}, it is another problem. See AngularJS : Insert HTML into view, the filter 'sanitize' in 2nd answer should help you ( call {{ '<h1>test</h1>' | sanitize }} and it should work.
EDIT 2:
In a js file:
angular.module('yourapp')
.filter("sanitize", ['$sce', function($sce) {
return function(htmlCode){
return $sce.trustAsHtml(htmlCode);
}
}]);
In view:
<div>{{value || '<h6>No Header for now.</h6>' | sanitize }}</div>
In dont know if you need 'ngResource' to use $sce, if it doesn't work, you will have to install angular-resource :/
I'm using a filter to calculate values, but then I want to access them later on.
Here's a snippet of my code:
app.controller('CreateProposalCtrl', function() {
$scope.EstimatedCostItem = [];
});
-
app.filter('EstimatedValue', function() {
return function(input, arguments) {
...blah blah calculations
return calculations;
};
});
I'm not sure how the HTML should be presented.
This displays exactly what I want..BUT I need it to set a variable so I can access it somewhere else..
<span ng-repeat="foo in bar">
{{ Type.JobTypeID | EstimatedValue: form }}
</span>
I've tried:
<span ng-model="EstimatedCostItem[Type.JobTypeID]" ng-bind="Type.JobTypeID | EstimatedValue: form"></span>
And:
<span ng-bind="EstimatedCostItem[Type.JobTypeID]">{{ Type.JobTypeID | EstimatedValue: form }}</span>
And:
<span ng-init="EstimatedCostItem[Type.JobTypeID] = (Type.JobTypeID | EstimatedValue: form)"></span>
Nothing seems to set a variable. I'm stumped :(
The filter syntax only works within specific Angular expressions. Expressions that use plain JavaScript cannot use the foo | bar filter syntax, as it's not valid JavaScript.
What you could do is use $filter:
var value = $filter('EstimatedValue')(foo);
Remember to inject $filter into your controller.
With that said, this probably isn't the best use of a filter. Why not create a scope function that calculates and stores the value? Something like:
$scope.EstimatedValue = function(foo) {
var value = doSomeCalculations();
// store for usage elsewhere
this.estimatedValuesCache[foo] = val;
return val;
};