Connect negative isDirty with a disabled class - ember.js

Is there a way to refactor the following code to make it cleaner or is a {{#if}} the cleanest way to solve this?
{{#if isDirty}}
<button {{action 'save' this}} class="btn">Save</button>
<button {{action 'discard' this}} class="btn">Discard</button>
{{else}}
<button class="btn disabled">Save</button>
<button class="btn disabled">Discard</button>
{{/if}}

I prefer to solve this with CSS:
<button {{bindAttr class=":btn content.isDirty:enabled:disabled"}}>Save</button>
You could use CSS to prevent the clicks when disabled (if your target browsers support it). Or just let the clicks go through and only call commit/rollback if content.isDirty.
Another option would be to bind the disabled property of the button:
<button {{bindAttr disabled="content.isDirty:enabled:disabled"}}>Save</button>

Related

How to identify button selected in cakephp 3.x?

I viewed the answer Which Submit Button was Clicked in CakePHP?. That situation doesn't apply to me, because I have the same action for each button.
I want to reuse a bootstrap modal and I want to know which item was selected when the modal was invoked. Very simply, I have a table with grades for each school object. When the user clicks the add button, I want to invoke the modal and add a grade for that object. I want to know which object was selected, because I want to reuse the modal for all objects. How can I do that in cakephp 3.x ?
After a teacher wants to add a grade and press the + button how do I know if he/she selected Mathematics or English if I use the same modal for grade saving? .
okey, most simple way is in modal to have hidden field, which contains a subject. I think this has not much to do with cakephp.
Example should look like this:
function modalopen(subject) {
$('#modal #subject').val(subject);
$('#modal').modal('toggle');
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js" integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
</head>
<body>
<button type="button" class="btn btn-info" onclick="modalopen('english')">+</button>
<button type="button" class="btn btn-info" onclick="modalopen('math')">+</button>
<div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-labelledby="" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id=""></h4>
</div>
<div class="modal-body">
sub (will be hidden):<br>
<input type="text" name="subject" id ="subject" value="" placeholder="will be hidden"><br>
Mark:<br>
<input type="text" name="mark" id ="mark" value="" placeholder="mark">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save</button>
</div>
</div>
</div>
</div>
</body>
</html>
The only way of determining which button was pressed is to use Javascript. This means not using the html-tag-option based method on the button to launch the modal, ie:
<!-- Button trigger modal: CAN *NOT* USE THIS TECHNIQUE!! -->
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
Launch demo modal
</button>
I assume the form inside your modal is a cake-generated form, and the submit button is a normal form submit, which triggers a redraw of the page, effectively killing the modal (IE there's no "modal takedown").
To keep as close as possible to Cake's paradigm, I would send it back to the server in a hidden form field.
Something like:
on the cake side in your ctp while creating your form:
// HTML WRAPPER FOR MODAL
<?= $this->Form->create(yourentity); ?>
(your form stuff)
<?= $this->Form->hidden("subject_id",["id"=>"subject-id-field"]);
(end of form stuff including submit)
<?= $this->Form->end(); ?>
// HTML WRAPPER FOR MODAL
This will generate something in your form like
<input type="hidden" name="subject_id" id="subject-id-field"/>
We'll need to grab this hidden field in Javascript, so I'm giving it both a name (form-specific) and an id (global), since I prefer referring to everything with #id-syntax, but you could also use form[name=subject_id] and get rid of the id clause
On the browser side in HTML, to create your buttons:
<button type="button" class="btn btn-primary" onclick="launch_dialog('MATH')">Add Math</button>
On the browser side in javascript, the function to call when the button is clicked, which sets the subject id in the form and then launches the modal/form:
<script>
function launch_dialog(subject) {
$("#subject-id-field").val(subject); // use the id of the hidden field
$("#your-modal").modal("show"); // or whatever you do to launch the modal
}
</script>
On the server side in the function that the form targets:
# in your controller php file
function formAction() {
if($this->request->data["subject_id"]=="MATH") { // use the name of the hidden field
// do math record
}
// etc
}
Another note - if your grade record really does have a subject_id field which belongsTo a Subject record, you can have the button's onclick function call the launch_dialog function with that constant, and then you won't need any IF function inside the server action code. Just make sure to use the original record to generate the id, eg:
In controller before render:
$this->set("subjects",$this->[entity]->Subjects->find("list");
In ctp file, something like:
<?php foreach($subjects as $id=>$name): ?>
<button type="button" class="btn btn-primary"
onclick="launch_dialog(<?= $id ?>)">Add <?= $name ?></button>
<?php endforeach; ?>

Insert component in Controller action EmberJS

well i need to insert a component when the user click on button, my code:
dash.hbs
<button class="btn btn-primary" {{action 'solisXTax'}}> Consul</button>
dash.js //controller
actions:{ solisXTax(){ "theCode" }, }
and my componenet is ember-chart,
{{ember-chart type="Bar"
data=solsGraph
width=500 height=350
options=opcionesGrafica
legend=true}}
Thanks
I don't know if you are familiar with the handlebars conditionals, but you should read more about that in the guides
You can use a conditional like so:
//templates/application.hbs
<button class="btn btn-primary" {{action 'solisXTax'}}> Consul</button>
<hr/>
{{#if componentVisible}}
{{ember-chart}}
{{else}}
no component shown
{{/if}}
with the corresponding action in your controller
//controllers/application.js
export default Ember.Controller.extend({
componentVisible: false,
actions:{
solisXTax(){
this.toggleProperty('componentVisible')
}
}
});
Here is a twiddle that showcases using an if statement to toggle your component.
You could also dynamically toggle between different components, where one could be a empty component, but that might be overkill for your use case.

how to add a class via binding in ember 2.0

I have a bootstrap button group in my Ember 2.2 app that looks like this:
<div class='btn-group' role='group' aria-label='...'>
<button type="button" class="btn btn-primary btn-xsm active={{aIsActive}}" >A</button>
<button type="button" class="btn btn-primary btn-xsm active={{bIsActive}}" >B</button>
<button type="button" class="btn btn-primary btn-xsm active={{cIsActive}}" >C</button>
</div>
'aIsActive', 'bIsActive', and 'cIsActive' are defined in the associated controller, and only one will be 'true' at a given time. The syntax shown above doesn't work. What's the proper way of doing this?
Here you go: if-helper
<button class="btn {{if aIsActive 'active'}}" >A</button>
btw, if you are creating navigation you should do it with link-to helper. It will add active class automatically when route is active.

ember dynamically change class name

In my ember application I would like to change button depending on if input change. Below is my code that is working fine but that code has redundancy.Is there better way to do it:
html code:
<div {{bind-attr class="isActive:active"}}>
{{#if isActive}}
<button class="primary button" {{ action 'saveData' }}>Save</button>
<button id="btn-cancel-info" class="secondary button">Cancel</button>
{{else}}
<button class="primary button inactive">Save</button>
<button id="btn-cancel-info" class="secondary button">Cancel</button>
{{/if}}
</div>
I am setting the value for isActive in objectController.
You can use the bind-attr helper.
{{bind-attr class="isNotActive:inactive :primary :button"}}
As you can see I added in your other Static classes as well, Below is a link to another question that is about static classes on the bind-attr helper.
Append a dynamic class to a view having a static class

ember-data handle server error

I am using ember-data 0.13 with rails. I have a basicinfo controller to handle basicinfo model update. update action is:
update: ->
#content.save()
#content.on('becameInvalid', (response) ->
alert Em.inspect(response.errors)
)
basicinfo.hbs:
<aside class='basicinfo-aside'>
{{#if inEditModel}}
<div class='control-group'>
<label for='basicinfo_about_me'>{{t '.basicinfo.edit.about_me'}}</label>
<div class='controls'>
{{view Em.TextArea id='basicinfo_about_me'
class='basicinfo-about-me'
name='basicinfo[about_me]'
valueBinding='aboutMe'}}
</div>
</div>
<div class='action-group'>
<span {{bindAttr class=':about-me-length-remain
hasAboutMeLengthRemain:muted:text-error'}}>
{{aboutMeLengthRemain}}
</span>
<button class='btn-cancel btn' {{action cancel}}>
{{t '.basicinfo.edit.cancel'}}
</button>
<button class='btn-update btn btn-primary' {{action update}}>
{{t '.basicinfo.edit.update'}}
</button>
</div>
{{/if}}
</aside>
<div class='basicinfo-inner'>
{{#unless inEditModel}}
<h5>
{{t '.basicinfo.about_me'}}
{{#if canManage}}
<a class='lnk-edit' href='#' {{action edit}}>
<i class='icon-edit'></i>
</a>
{{/if}}
</h5>
<p class='about-me'>{{aboutMe}}</p>
{{/unless}}
</div>
when I click update button with invalid data first time the error shows properly, but if I dont fix error and press update button again Ember shows: "Uncaught Error: Attempted to handle event willCommit on while in state rootState.loaded.updated.invalid. Called with undefined " How to solve it Thanks!
Ember data seems to be a little buggy when handling errors.
I would suggest you'd the following:
update: ->
#content.rollback() if #content.get('isError')
#content.save().then ((success_responce)->
<handle success responce here>
), (failure)->
<handle failure here>
Still a better solution in my opinion would be to disable the update button , based on the record.isError flag.
Another thing to consider is what to do when the server returns errors and you want to transition to another route (like with a cancel button).
Ember data will forbid you to ,complaining the record has inFlightAtrributes.
In this case you can again call record.rollback() to return the flags to initial state and continue your transition.