I'm trying to show and hide some buttons in Ember.js as follows.
{{#view App.myView contentBinding="App.myObject"}
<div id="my_widget" class="well span3">
{{#if content.isConditionTrue}}
<button id="stop_button" class="btn btn-primary"> Stop </button>
<button id="start_button" class="btn btn-primary" > Start </button>
<button id="record_button" class="btn btn-primary">Record </button>
</div>
{{else}}
<div id="widget_warning_box" class="well">
<p> No cameras are open, open a camera in Add/Remove Cameras tab. </p>
</div>
{{/if}}
</div>
{{/view}}
and the View looks like:
App.myView = Ember.View.Extend({
didInsertElement: function() {
$record = $("#record_button")
$start = $("#start_button")
$stop = $("#stop_button")
$record.click(function(){
console.log("record clicked")
});
$start.click(function(){
console.log("start clicked")
});
});
And the myObject controller is
App.myObject = Ember.Object.create({
isConditionTrue : false;
});
This sort of works (the buttons are replaced by the text if myObject.isConditionTrue is false, and appear when isCondionTrue is true) but when the buttons are displayed, they have no functionality on click. I guess its because they are not in the DOM when didInsertElement is called. So, is there some way to fix this? Should I do child/parent View setup? Any pointers appreciated.
Well I'm definitely not the guy who can tell what's the right way to do this, because I'm just learning ember too, but here is my working approach on fiddle
http://jsfiddle.net/drulia/zkPQt/
Basically every time you switching myObject.isConditionTrue to false, ember removes your buttons from DOM and that's why your jQuery selectors stops working. I attached ember js {{action}} helper and placed functions responding to the events in myObject, now buttons are working and showing action result on the screen.
Related
In the main html, there are two popup windows. one piece of code for one window is like this:
<div id="new-asset-modal" >
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header>
<h4 class="modal-title>Type A Record Name</h4>
</div>
<div class="modal-body">
<input ng-model="a" type="text" aria-describedby="basic-addon1" />
</div>
<div class="modal-footer">
<button type="button" data-dismiss="modal">Cancel</button>
<button type="button" data-dismiss="modal" id="modal-save" ng-click="add()">Save</button>
</div>
</div>
</div>
</div>
Ofcourse, there are anther modal called "Type B Record Name"
In the main html, I used directive like this
<directivetest></directivetest>
In the control, code is like this:
.directive("directivetest",function(){
return{
restrict:'EA',
replace: true,
templateUrl: "testpage.html",
controller:[ $scope,function($scope){
$scope.popaction=function(c){.....};
}]
}
);}
In the testpage.html, there is a button
<button ng-click="popaction(c);">Button1</button>
I want a function like this: When Button1 is pressed, if the argument equals to "a",then "Type A modal" is triggered/shown in the main page; if the argument equals to "b", then "Type B modal" is triggerd/shown.
Thank!!
One idea would be to $broadcast a message from your directive that contains the type that was clicked and then use $on in your main controller to listen for the message and act accordingly when received.
In the directive controller:
$scope.popaction=function(type){
$scope.$broadcast("BUTTON_CLICKED", {"type":type});
};
In the main controller:
$scope.$on("BUTTON_CLICKED", function(event, args) {
if(args.type === 'a') {
doModalA();
}
});
Update
As far as how to trigger the modal, I've used ng-dialog and really liked it. The documentation is pretty good but basically you include the js file and inject ngDialog, then do something like:
function doModalA() {
ngDialog.open({ template: 'popupTmpl.html' });
}
You can also use ngDialog.openConfirm and wait for a promise to return so you can perform actions based on the users interactions with your modal. You can also pass it data, your scope, give the modal it's own controller, and much more. It can be used very simply but it's very flexible to do more complex things.
Lastly, you'll probably have to make templates out of your modals, which is easy. Just include something like this in your main.html, put your modal content in it, and name it whatever you want:
<script type="text/ng-template" id="/popupTmpl.html">
Content of the template.
</script>
I'm running Meteor with Semantic UI as a framework .
I've got my main page on which I load X detail cards who all come from the same data source. All the detail cards have buttons, for example trash to remove the card.
I'm confirming actions on the buttons through modals.
I've got all of my modals in a separate template called modals.
From my main page I load my modals:
{{>modals}}
Inside my modals template I've got:
<template name="modals">
<div id="takeModal" class="ui modal">
{{#with data}}
<div class="ui header">
//HEADER
</div>
<div class="ui content">
// DATA USAGE IN TEMPLATE
{{city}}</td>
</div>
</div>
</template>
Above example is commented with // and just a fraction of the real thing.
The problem I'm running into is that I'm using the buttons on said card to call for the modal. The button eventhandler looks like:
Template.availablCard.events({
'click #checkmark': function () {
Session.set('data', this);
$('#takeModal').modal('show');
}
....
and the modal template has a helper:
Template.modals.helpers({
data: function () {
return Session.get('data');
}});
The problem I am facing is that the modals never function properly the first time because a click hasn't been registered yet and Session.data hasn't been set yet.
Is there a way to initialize the modals so they get loaded into the DOM, but still give them a data context?
ps. I've chosen this approach so I don't have to give every card it's own modal.
I use IronRouter to structure my app into controllers (routers), on which I started attaching my events. So far so good.
I then started using the {{#contentFor ...}} feature and since then, my events don't fire anymore, because the region I render the relevant element, is part of a different DOM tree.
Is there any approach to still listen to these events? I considered simply adding a global listener, but that would remove a lot of flexibility from the events.
CoffeeScript:
MyRouter = RouteController.extend(...)
MyRouter.events(
'click .inside': (event) ->
alert("inside") # works
'click .outside': (event) ->
alert("outside") # does not work
)
HTML:
<button type="button" class="inside">
inside
</button>
{{#contentFor 'anotherDomRegion'}}
<button type="button" class="outside">
outside
</button>
{{/contentFor}}
And layout file:
<h1>event demo</h1>
<div>
{{> yield}}
</div>
<div>
{{> yield 'anotherDomRegion'}}
</div>
I've run into the same problem myself. The only way I've been able to work around it is to set the contentFor to a template so you can assign your events to that template.
{{> contentFor region="anotherDomRegion" template="anotherDomRegion"}}
then;
<template name="anotherDomRegion"> ... </template>
and;
Template.anotherDomRegion.events({ ... });
Good luck!
I have a JSON structure that I'm passing into a Toolbar to try out dynamic compartmentalization in EmberJS. It looks like this:
{
draggable: true,
buttons: [
{label: "Portrait", action="vertical"},
{label: "Landscape", action="horizontal"}
]
}
I'm using it in a picture viewer that turns a photo vertically and horizontally. Because it's supposed to be a reusable toolbar for other parts of the application, I made it a Component and hooked the click event to the parent controller so it would turn the picture on click. I wanted the button to also get the active class like it does in other examples, but I think that's not working because of the embedded nature of the buttons. How do I get the button that gets clicked to get the active class so I can add css to it?
I tried setting an isActive property in each of the button objects in the model when init gets called and then setting that as true via the action function but I couldn't get observables to work with nested data structures. Do I have to make each button a separate component or can I avoid that?
Thanks for the help.
Templates
<script type="text/x-handlebars" data-template-name="photo-gallery">
<div id="PictureApp"></div>
{{#if toolbar}}
{{ui-toolbar options=toolbar buttonClicked="changeOrientation"}}
{{/if}}
</script>
<script type="text/x-handlebars" data-template-name="components/ui-toolbar">
{{title}}
<div class="overlay">
<div class="toolbar draggable">
{{#if draggable}}
<div class="header draggable-handle"></div>
{{/if}}
<ul>
{{#each buttons}}
<li{{action "clicked" this}}>{{label}}</li>
{{/each}}
</ul>
</div>
</div>
</script>
JS
App.UiToolbarComponent = App.Component.extend({
actions: {
clicked: function(context){
console.log(context);
this.sendAction("buttonClicked", context.action);
}
},
didInsertElement: function(){
if(this.get("draggable")) {
this.$(".draggable").draggable({handle: ".draggable-handle"});
}
}
});
It seems like you're on the right track. I think you could set the active property property on the button, however, you still need to set clear the active flag on any other button.
Inside the clicked action:
clicked: function(context){
console.log(context);
this.buttons.setEach('active', false);
context.set('active', true)
this.sendAction("buttonClicked", context.action);
}
Then on your template you can bind the class:
{{#each buttons}}
<li {{bind-attr class=active}} {{action "clicked" this}}>{{label}}</li>
{{/each}}
So I have an object of ArrayProxy kind
var App = Ember.Application.create();
App.car = Ember.ArrayProxy.create({
content:customers,
edit:function(e){
alert(e);
}
});
on my template I have an anchor tag with the action edit on click set to it by handle bars
<a class="primary action" {{action "edit" on="click"}}>Edit</a>
this isn't working and I think its because I can't set events on ArrayProxys... either that or something else?
Any help is appreciated. Thanks!
You can add a target to your action helper:
<a class="primary action" {{action "edit" target="App.car"}}>Edit</a>
And click is the default event, so you could remove the on ...