I using some angular 2 components in my project, and I need to change some of component's position. I use DOM to change the position first, like replaceChild or insertBefore, something like that. But I notice that angular 2 doesn't know the DOM change, seems like my DOM change is over the angular 2 life cycle. So, is there any way I can edit DOM in angular2 ? or some way I can change the order of components?
For you can understand what I'm doing, I'm building some components and I want to drag them and switch their position. I find a plug-in write in JQuery, you can find a gif on its GitHub site (https://github.com/Barrior/DDSort/blob/master/img/ddsort.gif). I want to implement something like that gif.
I find something maybe help on GitHub, but I don't know how to use it.
https://github.com/angular/angular/blob/master/modules/angular2/src/core/linker/view_manager.ts
I realize this was asked a while ago, but for others that might be struggling with something like this... Angular uses zones which I believe monkey-patch asynchronous JavaScript operations.
To trigger DOM updates that might not otherwise be picked up by Angular, you can run your with zones...
import { NgZone } from '#angular/core';
#Injectable()
export class SomeService {
constructor(private zone: NgZone) {}
someFunction() {
this.zone.run(() => {
// Your code goes here!
});
}
}
Take a look at this blog on zones
To follow the best practice, developers should use ViewChild to modify/use DOM. Here is an example to show how to use ViewChild to get a DOM element. You can use a "#" to mark the element you want to use and get it on your component.
If you want to get a collection of child elements in a component you should use ViewChildren.
The question was asked when I started to Learn Angular, it's stupid question and I believe there are many beginners like manipulate DOM directly. Please update your DOM in "Angular Way".
Related
I am making something similar to sheet with cells where using drag and drop i can move events, that are components, around.
Since it is possible to add component from any file like this
import event from "event.vue"
let el = document.getElementById("div")
const newComponent = createApp(event)
newComponent.mount(el)
Im trying to remove it somehow aswell, but i had no luck to find solution.
i have tried to this
let element = document.getElementById("newComponent")
element.parentNode.removeChild(element)
It's kind of working, but i can't add new component to same div because there is dataset remaining 'data-v-app' and i guess its because old component was not removed. Is there a way to do this or maybe vue isn't capable?
v-if is still the "official" way of doing things here because it uses Vue's reactivity.
Modifying the DOM is not recommended since it's imperative, like jQuery: you need to tell the language how to do things, so you need to take care of finding the selector, ask it to do things on it, and loop that process in case of an event listener or alike.
VueJS is declarative, so the API is far less complex. You tell what variable is bind to what and when the variable mutate, it will react accordingly to the changes without you needing to tell step by step what to do.
When you project grows, an imperative approach like jQuery or your vanilla JS (document.getElementById) will not be efficient because you will need to describe everything that happens once you mutate a variable. If 12 things depend on a thing, you will need pretty much the double of lines of code for each of them.
While in Vue, you will make some conditions thanks to the API and it will make those changes by itself. The complexity is then greatly reduced. On top of having powerful directives + Vue devtools to help you.
Add to that the fact that if you mix both some Vue state + imperative coding, you will have the worst of 2 worlds. You will need to do funky things to kinda keep the reactivity + will still need to write declarative code.
Hence why, people are using Vue's API + template refs only when needed.
Stay away from imperative coding: jQuery, manually selecting DOM elements etc...you will have an easier time, less complexity and more performance by far.
Vue/React exist for a reason, mainly removing complexity. Use them to their full potential.
I am trying to figure out a way to use Ember components as a view template for tooltips. Let me explain this:
I am supposed to create a library to show tooltips in Ember. The content of this tooltip is unknown. It might be very complex or it might be a simple text. The developer is the one who will decide it but the library must offer a way to do it easily. Also, I want to offer this solution in the format of an Ember modifier so that the developer would code it something like:
<div {{tooltip foo bar}}>
Hello World
</div>
As the modifier offers a reference to its element it is easy to use the good old JS to create elements and append them to this element. For a simple text it works like a charm and I was able to do it already as shown in the example below, but for complex component it's better to create a component and show it inside the tooltip's container.
// tooltip.js
import { modifier } from 'ember-modifier';
import { isPresent } from '#ember/utils'
export default modifier(function tooltip(element) {
const content = document.createElement('span')
content.append('Hi, I am the tooltip\'s text')
element.append(content)
});
The problem starts when you want to build a complex view, specially if it's supposed to contain some logic associated.
What I thought is that I could programmatically insert Ember components into the element that is passed as the argument of the modifier function. I can't use the dynamic component helper ({{component}}) as it infers that I have to mess with .hbs files more than what I am doing already and I can't approach it using the tooltip as a component; I need it to be a modifier.
I looked into this solution here but it doesn't seem to work in Ember 3.8.
Can anybody give me a clue on how do make it happen?
I am using Ember 3.8 and Ember Modifier#1.0.5
You could use the same technique that either of these use:
https://github.com/NullVoxPopuli/ember-popperjs
https://github.com/CrowdStrike/ember-velcro
They allow for "any content tooltips" by using an external library (popper or floating-ui, depending -- these are important though, because positioning is hard).
The gist is the following:
modifier on the "reference" / "hook" element (what you hover over)
modifier on the "target" / "popover" / "loop" element
some code that communicates between the two modifiers to wait until both are present before rendering the tooltip in the correct location / position.
The key part missing from your original code is that you need two modifiers -- tooltips with complex content are not possible with a single modifier (unless you manually manage element references).
For ember 3.8, I don't know how much you'll be able to do.
Ember 3.28 is the oldest LTS supported now and is passed its last bugfixes date, and it will step receiving security patches in January -- see: https://emberjs.com/releases/lts/
you may be able to use 2 global modifiers and a service to communicate between them -- but I don't know how that would work when you attempt to have multiple tooltips / popovers on the screen at the same time.
The minimum ember version you need to use the two addons linked above is 3.27.
Personally, it's well worth the upgrade, as staying up to date is generally easier than leap frogging years at a time (because you have the community doing upgrades with you) -- and shiny stuff is fun :)
Consider this function (this is just an example):
function highlight(el) {
el.style.transition = "background-color 0.5s";
el.classList.add("highlight");
setTimeout(() => {
el.classList.remove("highlight");
setTimeout(() => {
el.style.transition = "";
}, 500);
}, 500);
}
document.getElementsByTagName("a").addEventListener("click", function () { highlight(this) });
This is "universal function" that automatically binds to every <a> on page onload, it is short (only several lines long) and I can add or remove it in seconds (the code on pages are intact).
What is the best approach to implement it in React App?
Course I knew the obvious way, with the manual add of onClick to every <a> in every component on page with setState logic, but ... it kinda sucks
I'm new to React, maybe someone can point me to the right direction
How I can implement this logic on every page(every component that has <a>) efficiently, with the ability to easy remove it if it is no longer needed?
Well, the way I see it, if you want the react way, then you would want to create a presentation component with the defined behavior and use that component instead of .
In fact, that would actually be a perfect fit for a presentational react component.
Then, if you need to implement any changes, you would do them inside that component.
You could alternatively add vanilla js to the index page but that kinda misses the whole point of react.
If you are currently developing this application then the best approach is to create a small tiny component for it. For example you can create a component HighligtedAnchor and can implement the stylistic features in it directly.
Secondly, if you directly want to handle a lot of anchors then the most appropriate place would be the root of your application that is usually App.js or you can write it down in the index.html as well if you really want to move forward with the plane js approach.
If you are looking at for something like good old jquery live you can't do that in reactjs.
The best thing you can do is to create a custom component that wraps the <a> tag. And use your custom component everywhere you would use regular <a> tag.
I have to render a lot of divs into DOM. So, what I did is I render the first 5 elements into the DOM first after that I render every 10 divs with 300ms interval period.
The problem is when I change into display: block I need to change something in the component. So, I try to use didRender hook for that.
Code is below
didRender() {
if(this.element.offsetParent) {
this.set('myvar', true);
}
}
But it's not working perfectly. Anyone please suggest me which is the best way to do this.
_Thanks in Advance.
It's hard to guess your use case from the question but I assume that it's about rendering a very large list of items without causing performance issues. The ember ecosystem provides bulletproofen addons to do so. The most established ones I'm aware of are ember-collection and ember-large-list. I would recommend to use one of these if they suit your requirements. Reimplementing something similar will be a lot of work. Rendering new items on a timeout basis would not scale well as it doesn't take workload of browser into account.
For your concrete question: Ember does not provide a way to listen to CSS changes. You should execute custom logic at the same place as in which you are mutating the property which triggers the CSS change. If it has to be run after render, you need to deal with Ember's runloop.
I wan't to add some interactions to my Angular 2 project to enhance its user experience. I know how to interact with DOM, or change the status of element property. It is possible to write code for each of my component. But there are some examples which will be used site wide, for which I don't want to repeat the code everywhere I want to use it.
A simple example will the fade in when scroll elements. I know how to achieve this in a particular controller, but I need help to make this behaviour global without code repetition.
I Javascript / jQuery, we can have a master js file included which will have the event listeners bound to the elements, which is available for all pages. How to achieve similar in Angular?
This can mostly be done with Directives. Taking your example, you would create a [scroll-fade] Directive:
#Directive({
selector: '[scroll-fade]'
})
export class ScrollFade {
}
You'd then need to listen for the global scroll event, with #HostListener('window:scroll') and apply your styles to the :host element.
You would then use it by applying it to the elements you want affected:
<div class="scroller" scroll-fade></div>
If you need something more complex, you could always build a Shared Module where you would create reusable components, without repeating the code - which you could then transform into a library and share back with the community.
Theres an answer here on StackOverflow that explains how to.