can we change ngIf to hidden in Angular library explicitely - javascript

I am using Angular Material's Tab. And i am suppose to add and remove class using:
const classotherClustersSelection = document.getElementsByClassName('others');
Array.from(classotherClustersSelection).forEach(item => {
item.classList.remove('others');
})
On change of a particular data i am suppose to remove class from the tabs section, from all tabs. But unfortunately other tab that contains 'others' class is hidden with ng-if, so i am not able to manipulate the DOM directly. Whats are the approaches possible?

The issue is that *ngIf not hide the element, it removes it completle from the dom.
That's why you are not able to access the element.
If you want to hide something but still access it, you should remove the element by style.
You can use class or style binding for that:
style binding:
<div [style.display]="conditionForHide ? 'none' : 'initial'">
class binding:
<div [class.removeClass]="conditionForHide">
For the second option you need to create the class in you style sheet. An example to remove the element without display:
.conditionForHide {
opacity: 0;
pointer-events: none;
cursor: default;
width: 0px;
height: 0px;
position: absolute;
}
Edit
You should not manipulate the material code. And angular offers you a couple of options to manipulate your code next to plane javascript (getElementsByClassName).
The fastest way is when the data change is triggered, you manipulate the class via class binding:
Controller:
public showClassOthers = true;
onDataChange() {
// do some tasks
this.showClassOthers = false;
}
HTML:
<mat-tab-group>
<mat-tab label="First" [class.others]="showClassOthers"> Content 1 </mat-tab>
<mat-tab label="Second" [class.others]="showClassOthers"> Content 2 </mat-tab>
</mat-tab-group>

Add ngClass property to your div like I did below:
<div [ngClass]="{others: boolClass}" *ngIf="data==='requiredValue'"></div>
Then change the value of boolClass variable where the data gets changed:
this.data = 'someOtherValue';
this.boolCass = (this.boolClass)?(this.data==='requiredValue'): false;
Now the class will be removed from the element.
You can refer from my example here https://stackblitz.com/edit/angular-cc6tru

You can use ngClass to Conditionally add/remove the class from the DOM element.
demo
In Demo, I am changing the data on button click and based on the value class is added or removed.

Related

changing css custom properties in javascript

i've a JSX module(card.jsx) which is call in another component to create 5 instances of this module(card.jsx).
import card.css
...
<div className='cistern'>
<div className="shape">
<div className="wave"></div>
</div>
</div>
in my card.css, i have a custom property call filled.
.wave {
position: absolute;
--filled: 20%;
in my card.jsx i try to set different value for the css custom variable "filled".
React.useEffect(() => {
var cisternProperty = document.querySelector( '.wave' )
cisternProperty.style.setProperty('--filled', showFilledRoundString)
console.log('show Tank Level', showFilledRoundString)
}, [])
only the first instance use the new value, all other instance used the default "filled" value set in the css file.
what's happening? what could be the workaround?
thanks
To change the CSS property for every instance of an element in the .wave class you can either change the property in some common ancestor element rather than in the .wave elements themselves or you can go through all the .wave elements change their property.
So instead of using querySelector, which gives you only the first element in that class, use querySelectorAll which gives you a collection of all the elements in that class. You can then loop through them setting the CSS variable individually for each one:
var cisternProperties = document.querySelectorAll( '.wave' );
cisternProperties.forEach( cisternProperty => {
cisternProperty.style.setProperty('--filled', showFilledRoundString);
});

Custom HTML element that behaves like the built-in <div> elment

I want to create a custom HTML element that behaves exactly like the built-in <div> element. I'm trying to prevent a <div> soup. I would for example want to have a <currency-list> element. This element should behave exactly like the <div> element. The only difference is the name. How can I achieve this?
Thanks,
Yosemite
a DIV (HTMLDivElement) is a block element.
But you don't even need a defined Custom Element/Web Component to make a block element
customElements.define("currency-list", class extends HTMLElement {
connectedCallback() {
this.style.display = "block";
}
});
another-list {
display: block;
}
body>*:defined {
background: green;
color: beige;
}
body>*:not(:defined) {
background: lightgreen;
}
Line 1
<currency-list>Hello Web Component</currency-list>
Line 3
<div>Line 4</div>
Line 5
<another-list onclick="alert(this.constructor.name)">Line 6</another-list>
Line 7
Notes:
<currency-list> is an "Autonomous Custom Element" (extends HTMLElement)
You can extend HTMLDivElement in Chromium and FireFox, but Apple has stated they will never implement "Customized Built-In Elements"
From: https://github.com/WICG/webcomponents/issues/509
<another-list> is an HTMLUnknownElement; nothing wrong with using it, its constructor is an HTMLElement, so can do everything an HTMLElement can do.
For more on the value of Unknown Elements see my Dev.to post
You can set any CSS display value on a DIV, you can't on your own Elements, as it will destroy the display:block setting.
PS. tag your SO questions web-component and/or custom-element

Understanding Vue.js CSS Class Binding Ordering

Can anyone help me understand how to control the ordering of a component root element css class and any css class that may be bound from the parent calling the component?
Here is a fiddle that depicts what I'm noticing (snippet example below):
https://jsfiddle.net/cicsolutions/b6rnaw25/
You'll notice if you have a component with a class on its root element, if that class is a string, Vue's class binding places the class at the beginning of the resulting bound class list. This is what I would expect because because the component sets the base css class and then you can customize the styles when you use the component by adding classes to the component html element. Then Vue binds/joins the classes together.
In the next examples in the fiddle, I'm showing the use of a css class that is dynamic (i.e. not a static string). In these cases, Vue places the component's root element class at the end of the bound class list.
I'm working on a component that I hope others will use, so I'd like to set my component class on the root element, and then if anyone wants to override those styles, they can just add their own class on the component tag.
I also need the root element class to be dynamic, so I must use an array or an object to handle the class binding.
Does anyone know why Vue places the component root css class at the beginning for static classes and at the end for dynamic classes? That seems strange to me, but perhaps it's intentional for a reason that eludes me.
None the less, how would I go about ensuring that my component's root element class is always first in the resulting bound class list, when I need it to be a dynamic class?
Vue.directive('bound-class', (el) => {
const boundClass = el.attributes.class.nodeValue
const boundClassPrintout = document.createElement('div')
boundClassPrintout.innerHTML = 'Resulting Bound Class: ' + boundClass
el.appendChild(boundClassPrintout)
});
// STATIC CSS CLASS -> becomes 1st class in bound class list (expected)
Vue.component('string-test', {
template: `<div class="string-class" v-bound-class><slot></slot></div>`
});
// DYNAMIC CSS CLASS -> becomes last class in bound class list (unexpected)
Vue.component('array-test', {
template: `<div :class="['array-class']" v-bound-class><slot></slot></div>`
});
// DYNAMIC CSS CLASS -> becomes last class in bound class list (unexpected)
Vue.component('object-test', {
template: `<div :class="{ 'object-class': true }" v-bound-class><slot></slot></div>`
});
new Vue({
el: "#app",
computed: {
vueVersion() {
return Vue.version
}
}
})
body {
background: #20262E;
padding: 20px;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
}
h2 {
margin-bottom: 0.75rem;
}
<link href="https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2>Vue version: {{ vueVersion }}</h2>
<string-test class="p-2 mb-2 border">Root class (string-class) at beginning (expected)</string-test>
<array-test class="p-2 mb-2 border">Root class (array-class) at end (unexpected)</array-test>
<object-test class="p-2 mb-2 border">Root class (object-class) at end (unexpected)</object-test>
</div>
I suspect that there's no particular reason why Vue inserts static classes first; possibly it's just mirroring the order of the input parameters in the renderClass function.
Also the order of rule sets in CSS files matters; the order of class names in the class attribute of elements does not. And neither order has anything to do with the cascade, which refers to child elements inheriting styles from their parents. Perhaps you've confused that with the order of declarations within a block or within an inline style. In that case order does matter:
<p class="red blue">
Order doesn't matter in the class attribute above. If
the class styles contradict, whichever is defined last
will win regardless of how they're ordered in the attribute.
</p>
<p class="blue red">
This paragraph will be styled identically to the previous
one, despite the change in class order.
</p>
<p style="color: red; color: blue">
Order does matter here. The text color will be blue.
</p>

How to find class name from inspected code

When I inspected my web page I got this code
<li id="SR_R1_tab" class="t-Tabs-item a-Tabs-before a-Tabs-selected is-active" aria-controls="SR_R1" role="tab" aria-selected="true">
It is an oracle apex tabular region's sub region. I want to perform some css modifications and javascript actions in this class(sub regions of tabular region). How to find the exact class from this inspected code?. Should I use the class 't-Tabs-item' or 't-Tabs-item a-Tabs-before a-Tabs-selected is-active' ?
This element has 4 css classes:
t-Tabs-item
a-Tabs-before
a-Tabs-selected
is-active
In the debugger, you need to observe what each class does to your UI and you can decide which class to override.
Example: if you want to change the styling for each element, you will probably have to override t-Tabs-item:
.t-Tabs-item {
background: red;
}
But if you only want to change the appearance of the selected item, then you will probably have to override a-Tabs-selected. In that case you should also add the more generic .t-Tabs-item class in order to avoid side effects.
.t-Tabs-item.a-Tabs-selected {
background: green;
}
The li element you posted has the class attribute:
class="t-Tabs-item a-Tabs-before a-Tabs-selected is-active"
This means it has the following class names:
t-Tabs-item
a-Tabs-before
a-Tabs-selected
is-active
If you want to target only this li, by class name, and considering no other HTML elements have the same exact class t-Tabs-item a-Tabs-before a-Tabs-selected is-active, use this class name for selection:
.t-Tabs-item.a-Tabs-before.a-Tabs-selected.is-active { ... }
If you want to select any element which has the class name t-Tabs-item, use it as a selector, but consider that if other HTML elements in your page have this class, your selection would return multiple elements.
As per #str's comment to your question, if you want to target this specific li element, it's best to use an id selector:
#SR_R1_tab { ... }

How to using ng-repeat select all element, but without some class

How can I use ng-repeat to select all elements but exclude all of them which have a class bookmaker-disabled.
Screen shot
I am using: element.all(by.repeater('bookmaker in vm.bookmakers'))
What needs to be added here to get a result without elements with class bookmaker-disabled?
From looking at your screenshot, you add class 'bookmaker-disabled' when bookmaker.disabled is true. Well as per your code, you could add an ng-if="!bookmaker.disabled" to show only when not disabled, and remove elements which has disabled. In which case you needn't add the class.
Alternatively you could filter out those results which has bookmaker disabled, eg:
<div ng-repeat='bookmaker in vm.bookmakers | filter: {disabled: false}'>
Or you could use map reduce inside your controller if that was what you were looking for.
If you are using protractor, This might work:
element.all(by.repeater('bookmaker in vm.bookmakers')).filter(function(elem, index) {
return elem.getAttribute('class').then(function(classes) {
return classes.indexOf('bookmaker-disabled') === -1;
});
})

Categories