Rendering into an ember view's outlet - javascript

I have a view:
App.MyView = Ember.View.extend({
templateName: 'parent',
mouseEnter: function() {
// Do something
}
});
whose template has an {{outlet}}.
Here's the JS Bin: http://jsbin.com/ucanam/2779/edit
I'm trying to render into the outlet, and I can't figure out why it's not working. I tried putting the render call in an Em.run.next, because this issue is similar to https://github.com/emberjs/ember.js/issues/3626

Great question, but this isn't supported, here's some reasons:
The documentation specifies that the into is the route (http://emberjs.com/guides/routing/rendering-a-template/).
It's a dynamic view, which makes it an interesting problem, if you have multiple instances of the view, which would ember choose?
That being said you can still restructure the app to handle what you want
http://jsbin.com/ucanam/2785/edit

Related

remove template in renderTemplate ember route after loading is finished

i made a loading view when the route has to much waiting for the data, this is my route
import Ember from 'ember';
import ENV from '../../config/environment';
export default Ember.Route.extend({
desaService: Ember.inject.service(),
model(){
return Ember.RSVP.hash({
currentlyLoading:true,
desas: this.get('desaService').find(ENV.defaultOffset, ENV.defaultLimit),
desaCount: this.get('desaService').count()
});
},
setupController(controller, model) {
this.controllerFor('backend.master-desa').set('desas', model.desas);
this.controllerFor('backend.master-desa').set('currentlyLoading', model.currentlyLoading);
this.controllerFor('backend.master-desa').set('desaCount', model.desaCount);
},
renderTemplate(controller, model){
let controller2 = this.controllerFor('backend.master-desa');
if(controller2.get('currentlyLoading')){
this.render('components/common/loading-view', {
into:'application'
});
}
},
actions:{
loading(transition, originRoute){
let controller = this.controllerFor('backend.master-desa');
controller.set('currentlyLoading', true);
transition.promise.finally(function() {
controller.set('currentlyLoading', false);
});
}
}
});
first i set currentlyLoading true, then the renderTemplate will be called and showing 'components/common/loading-view' into application.hbs.
this is work but i need to remove that 'components/common/loading-view' after the loading actions has complete.
please help me :(
You can make use of disconnectOutlet method of router. What you need to do is to call the following to remove the template that is rendered within renderTemplate hook method.
actions:{
loading(transition, originRoute){
let _this = this;
let controller = this.controllerFor('backend.master-desa');
controller.set('currentlyLoading', true);
transition.promise.finally(function() {
controller.set('currentlyLoading', false);
_this.disconnectOutlet({
outlet: '',
parentView: 'application'
});
});
}
}
However, if you run your application probably you are going to see that nothing is rendered. Here is the reason:
renderTemplate hook is run after model is already solved; hence you will see nothing until the model is fully resolved. renderTemplate hook will be run to make a rendering; however loading event within actions will be fired and you will remove the template that is about to be rendered since loading is finished. Hence, you will not achieve what you want with this design approach.
You need to is to render something before model is fully resolved; and that is explained in the guide specifically. I suggest you to go over it and ask more if you run into some issues.
I have prepared the following twiddle for you that illustrates both usage of a loading template to show until model is fully resolved and usage of disconnectOutlet to remove a template that is rendered to a specific outlet. I hope this will help you understand better. Best Regards.
You doing it wrong, read the guide. All you need is to create a loading.hbs file and put html for loading screen there.
Also, if you want to create a loading indicator that will be displayed while assets are loading and application is starting, you can use this addon
Also, Your setupController can be simplified to controller.setProperties(model);. setProperties doc

insert component without calling handlebars helper or a controller with outlet

I want to insert a component into controller template without using the handlebars helper (component "component-name"... or component-name). Or through a controller in an outlet (or as long as the solution works for a component that wants to insert another component, then it's fine, I don't think outlets work in components).
In other words:
App.IndexController = Ember.Controller.extend({
actions: {
insertComponent: function() {
var component = this.container.lookup("component:my-inserted", { singleton: false });
component.set("layoutName", "components/my-inserted");
// to be like handlebars-inserted component, what do i do here?
}
}
});
You can use test with this: http://emberjs.jsbin.com/popozanare/4/edit?html,js,output
Why?
Thinking of a way of to have clean modal syntax, such as the "openModal" syntax described in the Ember Cookbook: http://guides.emberjs.com/v1.10.0/cookbook/user_interface_and_interaction/using_modal_dialogs/.
The problem is that the source context is lost, as the modal is within the ApplicationRoute. I want the same syntax when calling a modal, but keeping the hierarchy. You can keep the hierarchy using https://github.com/yapplabs/ember-modal-dialog, which requires a mapping of variables... which i don't like either (but will likely implement if I have no other choice).
TD;LR: Want to open modal within the controller/component (context) that called it without scaffolding in the controller/component that called it (mapping variables, etc).
Edit:
On second thought, using a container view might be cleaner than mapping variables, found in this solution: http://jsbin.com/hahohi/1/edit?html,js,output. Still needs scaffolding though. Thanks #user3568719.
That cookbook is a bit outdated, but if you are looking for a "clean" way to handling modals in your app I would suggest named outlets.
Add it to your application or auth template {{outlet "modal"}} and when you want to bring up the modal you can catch the action on the corresponding route and then render into that named outlet like so:
this.render('your-desired-modal-template', {
into: 'auth',
outlet: 'modal'
});
And when you want to dismiss it simply disconnectOutlet like so:
this.disconnectOutlet({
outlet: 'modal',
parentView: 'auth'
});
This is the way we've been going about it, I m open to suggestions/better methods.

How to reference ember.js controllers that are in nested folders?

I'm building an EventController that has little modules of logic within sections or div's of the event screen.
Say for instance, event details may be in the main Event template but a small section might be the user's status with the event such as whether they RSVP'd etc. but since it's controlled by a different model than the event I'd think it should have it's own controller.
Would I put this in the EventController like such:
Controller = BaseController.extend
needs: ['event/user-status-area']
userStatusArea: Ember.computed.alias("controllers.event.user-status-area")
This obviously isn't working otherwise I wouldn't be here... but I'm looking for suggestions.
I'm very new to ember / ember-cli concepts so I'm sorry if I'm just blatantly way off base here.
In my brain, I would imagine keeping everything about an event centralized under the one EventController...
Am I missing something big? Is this possibly where the "Router" comes in?
UPDATE:
If so, I'd imagine it might look something like this in Router:
Route = BaseRoute.extend
model: (params) ->
#store.find('event',params.id)
renderTemplate: (controller,model) ->
userStatusController = controller.get('userStatusArea')
#render 'event'
#render 'event/user-status-area',
into: 'event',
outlet: 'user-status-area',
controller:userStatusController
model: model.event_user.find(#get('session.current_user.userId'))
No idea if this would even be considered a best practice for ember?
I guess this would be the question... what is the best way to create this type of structure?
One way is to create a nested route:
router.js
this.resource('event',{path:'event/:id'}, function(){
this.route('userStatus');
})
in the event template, you would add an {{outlet}}
When you transition to event/{id}/userStatus, the outlet would be automatically rendered with the templates/event/user-status.hbs template.
When you reference controllers/views etc. in ember-cli with a filename e.g. user-status, you need to reference it in camelCase:
needs: ['event/userStatus'],
not user-status.
Hope this helps.

Ember.js - How to avoid manually rendering templates

I currently render my templates manually like so:
App.IndexRoute = Ember.Route.extend({
renderTemplate: function() {
this.render('index');
this.render('nav', {
outlet: 'nav',
into : 'index'
});
this.render('welcome', {
outlet: 'welcome',
into : 'index'
});
}
});
Now this works fine, but its been brought to my attention that best ember practices avoid manually rendered templates.
So I can understand that my index template should and would be rendered automatically dude to Ember awesomeness. However, how do I control the rendering of my nav and welcome templates inside of my index template? Is that something I handle in the router, controller? Or should I do it with handlebar partials?
Thanks.
in the template where you have your outlets replace it with template renders
instead of
{{outlet nav}}
use
{{render 'nav'}}
and you can completely remove the render section for nav. After you've done the same for welcome you can delete the renderTemplate hook altogether.
Additionally, there is nothing wrong with using the renderTemplate hook, it's a very accepted practice, granted in your case unnecessary.
read more about the render helper here http://emberjs.com/guides/templates/rendering-with-helpers/#toc_the-code-render-code-helper

ContainerView: limitations when dynamically adding views

ContainerView.pushObject() does not automatically wire-up dynamically added views with a Container object.
The lack of an auto-wired container causes a render failure when a view renders a template that contains a handlebars render helper.
SIMPLE CASE THAT WORKS (KIND OF)
View:
App.DynamicView = Em.View.extend({
templateName: 'dynamic',
didInsertElement: function() {
var control = this.get('controller');
control.send( 'view_inserted', this.templateName, control._debugContainerKey);
control.send('callDynamicController');
}
});
Template:
<script type="text/x-handlebars" data-template-name="dynamic">
dynamic
</script>
Controller (only used when manually assigned):
App.DynamicController = Em.ObjectController.extend({
className: 'App.DynamicWithRenderController',
callDynamicController: function() {
console.log('DynamicController.callDynamicController()');
}
});
Index Controller:
App.IndexController = Em.ObjectController.extend({
view_inserted: function(aview, acontroller) {
console.log('view inserted!', aview, acontroller);
}
})
Instantiation code:
var acontainer = App.DynamicController.create({});
var aview = App.DynamicView.create({ controller: acontroller })
acontainerView.pushObject(aview);
These classes render & behave as expected, but if you interogate them, lack some of the Ember-wiring (e.g. no _debugContainerKey & container properties IIRC):
MORE ADVANCED CASE THAT BREAKS
If we introduce a handlebars template that uses rendering helpers, it breaks rendering. The dynamically added view currently lacks some properties the rendering helper assumes
<script type="text/x-handlebars" data-template-name="dynamic-with-render">
dynamic w/render:
{{render knob}}
</script>
and make knob look like this:
<script type="text/x-handlebars" data-template-name="knob">
{{render knob}}
</script>
The (failing) dynamic view instantiation code:
var acontainer = App.DynamicController.create({});
var aview = App.DynamicView.create({
controller: acontroller,
template:'dynamic-with-render' })
acontainerView.pushObject(aview);
CODE EXAMPLE
A fuller example with some notes can be seen here:
http://jsfiddle.net/AshCoolman/KyJ2U/6/embedded/result/
NOTE: My tests include a custom handlebars helper based of the control helper called controlWithVars
THE PROBLEM
It looks like I need to write something that does the Ember-wiring, in either:
the more native ContainerView (getting into the Ember guts), OR
a more de-coupled new render helper possibly inelegant)
I'm not sure how to proceed. It would be great if someone has already come up with an elegant solution, or at least could give me some helpful tips.
EDIT: So it looks like creating and assigning a container, which includes the views dependencies might be a solution. Thoughts anyone?
HELPFUL READING
https://github.com/emberjs/ember.js/issues/2108
What is the purpose of the Ember.Container
http://mcdowall.info/posts/ember-application-initializers/
The raison d'ĂȘtre of Ember.ContainerView is for dynamically adding and removing views, so I'm pretty confident you can do all the things you want to with it.
One thing I noticed in your examples is that you are creating your child views with View.create(attrs). It is important to use containerView.createChildView(viewClassName, attrs) to create views that get the container, parent view hierarchy, and more. See the implementation more details:
https://github.com/emberjs/ember.js/blob/master/packages/ember-views/lib/views/view.js#L2072

Categories

Resources