How to remove global component completely in Vue? - javascript

I have a component called button-widget and it is registered globally.
Vue.component('button-widget', {
template: `<button>My Button</button>`
})
Now, how can I delete this component permanently?
I am not talking about v-if or $destroy() -- I just want to completely remove this component in such a way that it was never defined so that for example, I get this warning: Unknown custom element: <button-widget> - did you register the component correctly? For recursive components, make sure to provide the "name" option..

There is no public API to do this.
The correct solution is not to register it globally in the first place and instead just use it on a per-component basis by adding it to the components option of each component you want to use it in.
Otherwise you can unregister it like this:
delete Vue.options.components['button-widget']

Related

Difference in property binding for custom component in Ember V/s Angular

In Angular, if we want to bind a property from outside for a custom component, we have to use "#Input" to kind of allow that property to be set from outside (i.e. from consuming component template)
Does EmberJS also have some sort of similar mechanism OR does it allow binding directly from the template (hbs) without adding/marking anything in the component JS? Is there any difference when it comes to Ember Octane V/s the earlier versions of Ember?
yes it allows binding from outside the component without adding anything to the component js
in the component hbs file
<p>{{#attribute}}</p>
from outside
<MyComponent #attribute="attributeValue"/>
also you can get the binded attribute from component js
#tracked mycomponentAttribute = this.args.attribute;
in the component hbs file
<p>{{this.mycomponentAttribute}}</p>
no you don't necessarily have to add the input tag but you have to declare the property inside the component you are trying to pass the property to.
{{#each model as |post|}}
{{blog-post title=post.title body=post.body}}
{{/each}}
the blog-post component, define a property named title and this should work.

Is it possible to send an event from one component to another without using a global EventBus in Vue.js?

I have two components that do not have a parent - child relationship. They are not related to each other. But I am trying to make it so that when an event is emitted from one component then the other component can listen to that event and perform an action.
Here is an example, let's say that I have a component called "reset-component" and at some point it will emit an event called "reset".
<reset-component #reset="actionReset" />
And I also have a "grid-component" that should listen to the "reset" action emitted by the "reset-component" and perform some action.
<grid-component />
What are my options do accomplish this? The only solution that I can think of is to emit a global event using an EventBus and then have the grid-component listen to that global event. But is that a good idea? Isn't that more of an anti-patern?
// Reset component
EventBus.$emit('reset')
// Grid component
created()
{
EventBus.$on('reset', () => {
doSomething()
})
}
You can use Subject to accomplish this. See this link for more information: Vue.js + RxJS - Communicating Between Components with Observable & Subject
You actually have multiple options. But as you already answered yourself a global event bus is one of them
In your main file (assume something like main.js) you could do
Vue.prototype.$bus = new Vue()
By doing so you can now access this.$bus in every component e.g.
methods: {
dispatchReset () {
this.$bus.$emit('reset')
}
}
And other components can listen to it via
created () {
this.$bus.$on('reset', this.doReset)
}
Vuex is another option that was already mentioned by #Armen Armus in the comments. You could hold a global state for your application and dispatch events from within every component you want. However, if you really only want a few events like a reset I don't see a reason to add vuex.
Another option could also be to simply hold a "state" in your root Vue instance / component, but this would require you do pass down props and pass up events from within every view / component - and that would be quite annoying.
When passing props to child components and emitting events to parent components become hard because of distance or app complexity you can use VueX :
https://vuex.vuejs.org/
Yes you can use vm.$on and vm.$emit within components.
In your reset-component trigger the event from any method or element
this.$emit('reset')
and then you can then listen it,
<reset-component #reset="actionReset" />
You can also just add to the instances hooks:
ResetComponent.$on("reset", doSmth)
vm.$on
But i guess this will create a relation.

How does angular service (like ChangeDetectorRef) can get the component ref that used it?

I wonder how does this line work:
this.ref.markForCheck();
Or:
this.ref.detach();
While ref is: ChangeDetectorRef
I didn't see a way to get in a service the component that called you, so how does angular knows which component called it when I call this.ref.detach(); and detach the right component?
I would expect a call like this.ref.detach(this); so I pass the reference to the component, but seems like angular service has a way to access the caller?
Added jsfiddle https://jsfiddle.net/1hk7knwq/11788/
Look at the test() call, somehow the ref service is also getting the component instance without me explicitly passing it.
Thanks

How to add some action after component has been rendered?

First of all - I couldn't use reactcomponent over 'body'... Only inside a little . So
I need add two feature to my react components.
I need add run $(".nano").nanoScroller(); for component.
How to do it? componentDidMount - doesn't mean component (or subcomponent) is rendred?
When I need to add $(...).nanoScroller()
I made some strange with one action in .bind() "DOMSubtreeModified" (this mean, I hope, component DidRendered first time)
How to better way to handle "ClickOutside"? When I need (can) run handler? Also in DOMSubtreeModified?

Is my React component being recreated instead of updating?

I am trying to combine Angular and React.js. I have an work example project here I have seen a couple of ways to bring the Angular and React.js together. One of the methods I have seen is to create a directive and create the React component in the link function. For example in the first part of the project to generate the React version(in red) I am using
.directive('reactElementRepeater', function() {
return {
link: function(scope, element) {
var update_react = function(oldVal, newVal){ //Called every time one of the two values change
React.renderComponent(Demo_Element({
numberOfElements: scope.myModel.numberOfElem,
numberInElements: scope.myModel.numberInElem
}), element[0]);
}
scope.$watch('myModel.numberOfElem.length', update_react);
scope.$watch('myModel.numberInElem', update_react);
}
}
});
What I want and what should happen in a React enabled application is for something in the model to be updated, then that update is sent through React and it will alter the DOM as little as possible to reflect that change. It looks like that instead of updating a bit of the DOM this will Create a new React component each time with renderComponent.
React.renderComponent() instantiates the root component, starts the
framework, and injects the markup into a raw DOM element, provided as
the second argument.
Is it actually recreating the elements each time? If that is the case is there a way to alter this so that doesn't happen?
Just to be clear I know about ngReact, I just want to know other ways to speed up Angular with React.
Yes this is fine, it's not mounting the component multiple times.
When you call React.renderComponent() the second argument is the element which react should render the component to. So react notices if you are rendering the same component to a dom element that already contains a mounted instance of the component, and does not re-mount the entire component, it just updates the properties of it instead.
You can see this in action if you make a component with componentDidMount function defined. You'll notice that componentDidMount will only execute the first time renderComponent gets called. And afterwards, subsequent calls to renderComponent on the same target dom element will not call it because the component is already mounted. Likewise getDefaultState and getDefaultProps also only get called on the first renderComponent call.
If you're asking will the render function of the component be called every time the answer is yes. But this is how react works, you want the render function to get called because props might have changed. You can block it from being called by using shouldComponentUpdate (http://facebook.github.io/react/docs/component-specs.html#updating-shouldcomponentupdate) and returning false. However react developers recommend you don't use this to block render calls unless you have specific performance problems - most of the time it should be fine to just let the render call execute as it wont cause any slow dom updates unless things have actually changed.

Categories