What's the difference between ".yy & .xx {...} " and ".yy .xx {...} " in stylus? - stylus

What's the difference between "A" and "B " in stylus ?
A:
.yy
& .xx
{...}
--------
B:
.yy
.xx
{...}

In A, the use of the & signals that the two classes apply to the same element. That is, you'll match an element like this:
<div class="yy xx">...</div>
In B, the two selectors are nested. So you'll match any class='xx' inside a class='yy'.
<div class="xx">I don't match</div>
<div class="yy">
<div class="xx">I match</div>
</div>

This is the same expressions.example A is redundant. By default, there are nesting in Stylus. So you can always use the example B

Related

ngClass Directive: Can I use multiple expressions to add multiple classes?

Here is an example of what I want to achieve
data-ng-class="{ 'tooltip_show' : showTooltip , 'tooltip__' + brand.settings.name }"
but it doesn't work.
Use the array form for ng-class:
<div ng-class="[showTooltip ? 'tooltip_show' : '',
'tooltip__' + brand.settings.name]">
<div>
OR compute the class in JavaScript:
<div ng-class="computeClass(tooltip_show, brand.setting.name)">
</div>
$scope.computeClass(show, name) {
var obj = {};
obj.showTooltip = show;
obj['tooltip_'+name] = true;
return obj;
};
The later approach is more easily debugged and better for complex computation.
See also,
AngularJS ng-class Directive Reference - Known Issues
AngularJS Developer Guide - Why mixing interpolation and expressions is bad practice
It looks like you haven't set a value for the second item. Did you mean something like
{ 'tooltip_show' : showTooltip , 'tooltip__' + brand.settings.name : tooltipText }
or
{ 'tooltip_show' : showTooltip , 'tooltip__' : brand.settings.name }
?
http://jsbin.com/genaqapefe/edit?html,js,output
data-ng-class="{ 'tooltip_show': showToolTip, {{ 'tooltip_' + brand.settings.name }}: true }"
This is working for me in this bin. I couldn't get it to evaluate without the curly braces, although not sure if that's the best practice.

ng-class with multiple options

I'm fetching data using a REST API and one of the attributes returned can be any of 3 options;
The options are; Negative, Warning, Success.
I want to set a class using ng-class based on the value returned;
I'm able to do this but only for one;
Code below;
<div class="alert" ng-class="restaurantNotice(restaurant[0].notice)" ng-if="restaurant[0].notice.length">
<div class="alert-inner inner-large" ng-bind="restaurant[0].notice"></div>
</div>
$scope.restaurantNotice = function(a) {
return (a = Negative) ? 'negative' : '';
};
As you can see, if a = Negative then a class negative is applied else nothing is applied.
Now I want to check for all three options and apply 3 different classes respectively
Instead of function in ng-class, use object
ng-class="{'negative' : restaurant[0].notice == 'Negative', 'warning' : restaurant[0].notice == 'Warning', 'success' : restaurant[0].notice == 'Success'}"
You can try
<div class="alert" ng-class="{'negative' : restaurant[0].notice.length, 'warning' : restaurant[1].notice.length, 'success' : restaurant[2].notice.length}">
<div class="alert-inner inner-large" ng-bind="restaurant[0].notice"></div>
</div>
duplicate of Adding multiple class using ng-class
In this way:
<p ng-class="{a: deleted, b: important, c: error}">Example</p>
if a is true, apply class deleted, and so on.
If you are just going to set the same notice type (Negative, Warning, Success) as class then just convert to lower case and return from the function instead of putting conditions.
$scope.restaurantNotice = function(a) {
return a.toLowerCase();
};
OR
<div class="alert" class="{{restaurant[0].notice | lowercase}}" ng-if="restaurant[0].notice.length">

AngularJs FilterBy property a in array A, where a exists in array B

I am using angular-filter and I want to loop the collection A and only display items where A.a exists in array B.
A = [{a:'mouse', c:'Tom'}, {a:'cat', c:'Jerry'}];
B = ['cat', 'dog'];
Then, I want something like:
<div ng-repeat="item in A | filterBy: ['item.a'] : B">
{{item.c}}
</div>
Would return: <div>Jerry</div> because cat is in B. I imagine that I can achieve this with pick, but was wondering if I can do this with filterBy?
if using lodash will do for you and you are not married to the filter idea. here is a quick solution.
define on the scope a function that gets the selected ones and bind that to the ng-repeat:
$scope.commonItems = function(){
return _.filter(A, function(itemA){ return _.includes(B, itemA.a) })
}
and then:
<div ng-repeat="item in commonItems()">
{{item.c}}
</div>

ngClass string binding expression with class map

Is it possible to use ngClass with an expression AND a class map? I want to conditionally add a class based on the existence of a variable as well as use that variable in the expression that creates the class.
For instance, if isActive() is true and getStatus() returns "valid" I want the class list to be "element element--active element--valid". If getStatus() returns undefined I want the class list to be "element element--active".
<div
class="element"
ng-class="{
'element--active': ctrl.isActive(),
'element--{{ ctrl.getStatus() }}': ctrl.getStatus()
}"></div>
Doesn't seem to work.
<div
class="element element--{{ctrl.getStatus()}}"
ng-class="{
'element--active': ctrl.isActive()
}"></div>
Works but then there's an extra hanging "element--" if getStatus() returns undefined.
Do I have to add a method in my controller to handle the class generation?
i'd suggest to make just one function call to get the classes. It will make it cleaner and have the class logic in one place.
In your controller:
this.getElementStatus = function(){
var rules = {active:this.isActive()}; //Prefix with element-- {element--active:}
rules[this.getStatus()] = true; //Prefix with element--, rules['element--' + this.getStatus()] = true
return rules;
}
and your view would just be:
<div
class="element"
ng-class="ctrl.getElementStatus()"></div>
It seems like your element-- is redundant with the rule instead make use of cascadeability(CSS) property. and define rules as :
Example:
.element.active{ /*....*/ }
.element.success {/*...*/}
.element.error{/*...*/}
This will help in maintenance, gets more verbose and get to the natural way of adding css rules and could remove these kind of complexities from the view.
You could as well do:
<div class="element"
ng-class="{'active': ctrl.isActive(), '{{ctrl.getStatus()}}':true}"
or :
<div class="element"
ng-class="[ctrl.isActive() ? 'active' : '', ctrl.getStatus()]"
If you don't mind getting a true added as a rule(should not affect anything anyways) then,
<div class="element"
ng-class="[!ctrl.isActive() || 'element--active' , 'element--' + ctrl.getStatus()]">
You can use class and ng-class map on the same element. But since your class name is dynamic you will have to something like this.
<div
ng-class="'element '
+ (ctrl.isActive() ? ' element--active' : '')
+ (ctrl.getStatus() ? ' element--' + ctrl.getStatus() : '')"></div>

Add an extra Capital letter element only at the start of each new letter in ng-repeat

I have an array sorted like so:
[aa,ab,ba,bb]
I want to render it like this:
A
aa
ab
B
ba
bb
how can I modify this forech to do this?
<div ng-repeat="item in array" >
{{item}} <br>
</div>
You can do it like this :
$scope.capitalize = function(array){
//group all elements by first letter using lodash
var items = _.groupBy(array,function(element){return element.charAt(0)});
//flatten object arrays to one array
return _.flatten(items,function(elements,letter){return [letter.toUpperCase(),elements] });
}
and on html you have
<div ng-repeat="item in capitalize(array)">
{{item}} <br/>
</div>
Working fiddle :
http://jsfiddle.net/qmw0qp6p/4/
I added also #sameer resolution, but it is not what you want.
I think you don't want to print the words and their first letters like you did in the question, but more like this:
A
- aa
- ab
B
- ba
- bb
To do so, I would aggregate the strings by their first letter using a custom groupBy filter (reusable), and then simply loop on the obtained object.
See this JSFiddle.
The cache system I implemented allows fast access to already computed results and avoids infinite digest loop (occurring because a new object is each time returned by Array.prototype.reduce).
Please try the below code
angular.module('module', []).
filter('capitalize', function() {
return function(input, all) {
return (!!input) ? input.replace(/([^\W_]+[^\s-]*) */g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}) : '';
}
});
and In HTML
<div ng-repeat="item in array" >
{{item | capitalize}} <br>
</div>

Resources