i have an SPA designed using features (collection of components).. each component exposes bindable properties and some observable properties for inner state management.. the feature at the top level also exposes bindable properties that are used in implementation views to render out specific funcitonalities.. each feature has data dependencies that pull from APIs and some features depend on each other for values that are bound after data loads...
the problem - how do I best handle app initialization when there's changed events firing from observable/bindable properties all through that initial load. my first thought is to find a way to disable all observable in a single place in code that i then turn on once everythign is loaded and ready to start reacting to cascading changes... does that exist in some low-level aurelia API? the only other alternative is to carefully and tediously map out all dependencies and sprinkle "if(!isInitialized) then exit" statements everywhere but that sounds horrible...
That really depends on when you hydrate your components.
The docs here: http://aurelia.io/docs/fundamentals/components#the-component-lifecycle say that if you do something to properties in bind() lifecycle handler - the change handlers would not be called.
Related
I have a component that will have a set of states, in which each state has a set of UI events and response methods. Some of the UI events may not be included in all the states.
My current idea is to create a controller interface including methods for each possible UI event that the component can then call in response to each event. Each state will then have a corresponding implementation of the interface. The main issue here is that many of the concrete controllers will have empty methods being called.
To avoid this issue, the only solution I can think of is to not even use Angular directives and have each concrete controller create its own event listeners. While this would avoid the previous issue, I am wondering whether there's a better approach relying on Angular features.
We have an old legacy MVC app that has a mixture of UI technologies in it, from razor pages, to JQuery to Vue native.
The problem I have is that the new vue components work great in isolation, but we want to instantiate the component and it's properties from an old javascript file.
Can this be done outside of the Vue entry script?
Essentially we have a Js file that loads a customer and at that point we want to bind the vue component with the customer id. I thought we could use the data dictionary to set the data attribute (which I believe vue maps to the prop) but that doesn't seem to work (there is a watch on the property).
The vue component is being used elsewhere, which is why I don't want to change it.
In a pinch, you can access and modify Vue2 internals from external code using the __vue__ property bound to the DOM element Vue was instantiated on.
This is not officially supported, but Vue's creator says "the official devtool relies on it too, so it's unlikely to change or break." https://github.com/vuejs/vue/issues/5621
I'd recommend keeping the amount of manipulation you do this way to a minimum, but reaching in to set a customer ID should be reasonably straightforward.
(In Vue3 this is somewhat more complicated; you need to do the DOM binding yourself from within Vue.)
I'm looking for some guidance with regards to managing state in a real-time messaging/chat app built with VueJS 2.
The app consists of several components which are outlined in the following diagram:
So far, I've implemented displaying (fake) conversations. The App component contains an array with conversation objects. For each child component, the relevant data is passed using props. This is really simple and works like a charm.
Now, I have to deal with actions/mutations from components deeply nested in the tree. For example, sending a message and appending it to the corresponding array of messages.
I figured it would be as easy as dispatching a (global) event in the AppConversationChatWindowInput component and handling it in the App component. Boy was I wrong. Apparently, this functionality was removed when Vue 2.0 was introduced in favor of Vuex. I'm not sure why it was removed, because in some situations this could be a perfectly reasonable way to deal with events.
I guess there are a couple of possible solutions:
Passing the websocket connection to each child component. This could technically work. The App would connect to the websocket server and pass this connection to its child components using props. When the user sends a message, it is echoed by the websocket server. The App component can listen for the message and append it to the array of messages.
Regardless of the technical feasability, this feels like a crappy and hard-to-maintain archicture to me. In my opinion, no component other than the App should be aware of the websocket connection, let alone its concrete implementation.
Manually bubbling up the event in each component in the chain.
This seems like a complete pain to maintain. Introduces a lot of needless complexity and failure points.
Using a global event bus.
This is possible, but why should an input field depend upon a global event bus? I don't like unnecessary dependencies and coupling. It adds complexity and makes things harder to test.
Using a global data store (Vuex).
See #3. Another dependency and added complexity. Also, if I would settle for Vuex, how would I retrieve data in my components? Do I pass it down using components (like I do now) or would a component deep down in the tree just grab it from the store directly? To me, it feels like the component knows a lot more than it should this way.
Any thoughts? What's the best way to handle state in my situation?
There's a bit of a disconnect between "I wanted to dispatch a global event" and "I don't want to use a global event bus." A global event bus is how you dispatch/broadcast a global event. It is, as you note, a good solution in some situations. It is not hard to set up when you need it, so there's no strong reason for it to be in core Vue.
You can create the bus as an instance property on Vue so it is available to every component:
Vue.prototype.$globalEventBus = new Vue();
Where you would have had vm.$dispatch(...) you would do vm.$globalEventBus.$emit(...) and the receiving component can set up vm.$globalEventBus.$on(...).
Alternatively, you could create a bus at the top level and pass it through the children as a prop. This avoids globals, and you don't have to worry about bubbling.
Finally, as I noted in my comment, native events bubble, and you can catch them at any component higher up the chain. You could catch the event(s) that send messages, or even roll your own events to catch.
I'm new to ReactJS and I'm trying to figure out how to store and manipulate global state. For example, I'm writing an editor app that has some global state: selected color/background, active tool, current selection, etc.
I'm thinking about having a root interface component to store this information, and I'm ok with explicitly passing the state around using properties. I guess the idiomatic way for a children component to change global state is calling a callback received from the parent - personally I find this a bit annoying.
Instead, I'm firing custom events at the children and setting listeners on the parent. So far it is working really well, but I looked at a lot of sample code and never saw people using this pattern.
Is there any practical consequences I should consider?
Flux is great for manipulating global state because the Stores are globally accessible. Globals are known to be bad, but the way you interact with the Stores is through Actions. Actions make the state predictable and localized. So even though the state storage itself is global, Actions make the state interactions very local. At work we tend to do both reading & writing through Actions, so every state change is an "event" that leads to easily programmable behavior.
I really wouldn't compare Flux to Angular as their principles and flows are entirely different. Suggest you try Reflux.
The following is from an issue I posted on EmberJS GitHub, but Stack Overflow is better suited for a discussion than GitHub.
I am building a few complex components at the moment including composite components and I hit a roadblock with the extreme isolation components live in.
There are several cases where I don't need the components to trigger an action on a controller, but where a controller needs to trigger a behaviour change on the component.
Problems is that the components don't know about the controller and the controller is not creating the components either: they are defined in a template.
I kind of solved the problem by subclassing the Ember.Component class to offer a way for messages to get through components.
The new component subclass breaks the on purpose isolation of components that shouldn't know about the outer controller.
The 2 less invasive options I found to make component methods calls from outside are:
Cache component / name of instance pairs in a global array like
App.components, then call a component method with
App.components['name'].method()
Trigger events from outside, register and handle them in the
components. However in that case I am passing an eventSource object
to the component, often a controller like so: {{my-component
eventSource=controller}}
My question is about how could we solve this problem in the most elegant and less invasive way possible for components ?
For achieving composite components, using the components like lego pieces, it seems impossible to me at the moment to see how we can achieve that goal without breaking the components isolation.
Any input, ideas, solutions, discussion is very welcome.
Note: By the way, the first method that breaks the component isolation is inspired by the work done on the ember-bootstrap components: https://github.com/ember-addons/bootstrap-for-ember
The author had to solve the same problem of being capable of triggering methods inside the components from outside.
Another note: Just for the record, another way to access a component is to use Ember.View.views['name'] where name is a view name you gave to your component. However I feel dirty to make such calls, even more from a controller.
In general, I would try to solve this by binding properties to your component, which could then change according to computed properties or observers based on those properties.
For instance, instead of trying to call a method like deactivate on a component, bind a property such as active to a property in the template:
{{my-component active=formEnabled}}
I'm hesitant to recommend passing an eventSource to components as a general solution (like your {{my-component eventSource=controller}} example). I imagine this could work with a class or mixin that just emits specific events and is tightly coupled with your component, but I'm struggling to come up with a use case that justifies this approach.