I have a simple input radio for toggling between active and inactive. I can not figure out how to get Ember to tie this to the model. My RAW html currently looks like this:
<fieldset class="checkboxes">
<label class="active" for="is_active">
<input type="radio" id="is_active" name="status" value="1" checked="">
<span>Active</span>
<div class="input"></div>
</label>
<label class="sep">/</label>
<label class="inactive" for="inactive">
<input type="radio" id="inactive" value="0" name="status">
<span>Inactive</span>
<div class="input"></div>
</label>
Does anyone have any ideas on how to do this using the Ember form model binding?
make your labels action, that will allow you to play with them in the controller. I hope this help....
<fieldset>
<label class="option-buttons" for="reason1" {{action "setDeclineReason" "Too Expensive" on="mouseDown"}}>
<input name="decline-reason" id="reason1" value="Too Expensive" type="radio">
<span>
<div class="check"></div>
Too expensive
</span>
</label>
<label class="option-buttons" for="reason2" {{action "setDeclineReason" "Lack of Amenities" on="mouseDown"}}>
<input name="decline-reason" id="reason2" value="Lack of Amenities" type="radio">
<span>
<div class="check"></div>
Lack of amenities
</span>
</label>
</fieldset>
App.DeclineController = Ember.Controller.extend({
declineReason: null,
decline: function(){
var update = this.store.update('request', {
id: this.get('model').id,
user_decline_reason: this.get('declineReason')
});
update.save();
actions:{
setDeclineReason: function(declineReason){
this.set('declineReason', declineReason);
}
}
});
Related
I'm having trouble with uploading images in Ember.js
I have a form to create a user :
<div class="container">
<form onsubmit={{action "createUser"}} enctype="multipart/form-data">
<div class="form-group">
<label for="firstName">First name: </label>
{{input type="text" class="form-control" id="firstName" required="true" value=firstName}}
</div>
<div class="form-group">
<label for="lastName">Last name: </label>
{{input type="text" class="form-control" id="lastName" required="true" value=lastName}}
</div>
<div class="form-group">
<label for="age">Age: </label>
{{input type="number" class="form-control" id="age" required="true" value=age}}
</div>
<div class="form-group">
<label for="job">Job: </label>
{{input type="text" class="form-control" id="job" required="true" value=job}}
</div>
<div class="form-group">
<label for="image">Picture: </label>
{{input type="file" class="form-control" id="image" value=image}}
</div>
<button type="submit" class="btn btn-info">Create</button>
</form>
I know I should encode images in base64 but I have no idea how to do that since I've never done it before.
And in the view, this is how I'm trying to get the image (I know this is not what I should do but I don't know how to do it) :
<div class="container">
<h1>{{model.firstName}} {{model.lastName}}</h1>
<p>Age: {{model.age}} years old</p>
<p>Job: {{model.job}}</p>
<img src="{{model.image}}" alt="img" id="image">
</div>
Any ideas, suggestions, help please ?
EDIT :
actions: {
createUser(event) {
event.preventDefault();
let user = this.store.createRecord('user', {
firstName: this.firstName,
lastName: this.lastName,
age: this.age,
job: this.job,
image: this.image
});
user.save().then (() => {
this.transitionToRoute('user', user.id);
});
}
}
Make use of ember-file-upload addon. The addon takes care in encoding them as a Base64 data url. In your case follow the below steps,
hbs form page:
<form onsubmit={{action 'createUser'}}>
<div class="form-group">
<label for="firstName">First name: </label>
{{input type="text" class="form-control" id="firstName" required="true" value=firstName}}
</div>
...
//other input fields
...
{{#file-upload name="avatar"
accept="image/*"
onfileadd=(action 'setAvatar')}}
// preview image before uploading
{{#if avatar}}
<img src={{avatar}}
<a id="upload-avatar">Add a photo</a>
{{else}}
<a id="upload-avatar">Add a photo</a>
{{/if}}
{{/file-upload}}
<button type="submit">Create</button>
</form>
hbs view page:
<div class="container">
<h1>{{model.firstName}} {{model.lastName}}</h1>
<p>Age: {{model.age}} years old</p>
<p>Job: {{model.job}}</p>
<img src={{model.image}} alt="img" id="image">
</div>
js:
import Controller from '#ember/controller';
export default Controller.extend({
avatarFile: null,
actions: {
createUser(event) {
event.preventDefault();
// upload file to backend
let file = this.get('avatarFile');
// make a api call to the url `/upload` (modify the url as you wish)
file.upload('/upload').then((response) => {
// save user model once the image is been uploaded successfully to the server
let user = this.store.createRecord('user', {
firstName: this.firstName,
...
// get the image_url from backend response
image: response.image_url
});
user.save().then((response) => {
// get the user_id in response
this.transitionToRoute('user', response.user_id);
});
});
},
setAvatar(file) {
this.set('avatarFile', file);
// Set the URL so we can see a preview
file.readAsDataURL().then((url) => {
this.set('avatar', url);
});
}
}
});
You can refer to the entire documentation here
Replace
{{input type="file" class="form-control" id="image" value=image}}
with
<input type="file" class="form-control" id="image" onchange={{action "uploadFile"}}/>
<br> Chosen image is <br>
<img src={{image}} />
This will trigger the uploadFile action when the image is chosen.
In your js file, add the action as ,
actions: {
uploadFile: function(event) {
var self = this;
const reader = new FileReader();
const file = event.target.files[0];
let imageData;
reader.onload = function(){
imageData = reader.result;
self.set('image', imageData);
};
if (file) {
reader.readAsDataURL(file);
}
}
}
Source : https://stackoverflow.com/a/40370830/2824131
I put this layer on all pages on my website(layout) and I want to hide this layer when user type password(hello) using cookie.
I tried to mix two sources but it doesn't work :(
Can you guys help me? thanks :)
--- HTML ---
<div class="popPass">
<div class="passcode aligncenter">
<form name="loginpage" action="javascript:;" method="post" onsubmit="return LogIn( this );">
<div class="input nobottomborder">
<div class="inputcontent">
<input type="password" id="password" /><br />
</div>
</div>
<div class="buttons">
<input name="Submit" type="submit" value="Login">
</div>
</form>
</div>
</div>
I think I missed something.
From your fiddle, you defined your LogIn function inside the jQuery ready callback, which is not in the global scope. So the onsubmit handler can't access it. Try to lift it to the global scope.
In a custom template (website) I've added an input tag. I'd like to get the value of this tag in order to send it to the controller. By adding this to the URL, but I always get 'None' back.
<template id="InputTemp" inherit_id="website_sale.cart">
<xpath expr="//div[#id='right_column']" position="after">
<div class="col-lg-3 col-lg-offset-1 col-sm-3 col-md-3 text-muted" id="inputform">
<h3>Please enter value:</h3>
<label class="control-label" for="waardebon">Value</label>
<input type="text" name="value_input" class="form-control"/>
<a t-attf-href="/cart/#{str(value_input)}" class="btn btn-primary btn-lg mt8">Submit</a>
</div>
</xpath>
</template>
Your t-attf-href is rendered before any data has been entered into the form field. To do it the way you are you need to update your href using javascript. In odoo9 you need to use requirejs syntax to load the proper libraries to run a post request to your controllers. If you are just using a get request then the following should work for your example.
<template id="InputTemp" inherit_id="website_sale.cart">
<xpath expr="//div[#id='right_column']" position="after">
<div class="col-lg-3 col-lg-offset-1 col-sm-3 col-md-3 text-muted" id="inputform">
<h3>Please enter value:</h3>
<label class="control-label" for="waardebon">Value</label>
<input type="text" name="value_input" id="value_input" class="form-control"/>
<a id='submit-btn' t-attf-href="#" class="btn btn-primary btn-lg mt8">Submit</a>
<script>
var value_input = document.getElementById('value_input');
var submit_button = document.getElementById('submit-btn');
value_input.addEventListener('input', function(){
submit_button.href = "/cart/?input_value=" + value_input.value;
});
</script>
</div>
</xpath>
</template>
Here is an example controller.
#http.route('/cart/', auth='public', website=True)
def get_cart_vals(self, **kw):
# YOUR VARIABLE value_input SHOULD BE AVAILABLE IN THE QUERY STRING
query_string = request.httprequest.query_string
# PROCESS DATA AND LOAD THE RESPONSE TO THE USER OR REDIRECT HERE
template.xml
<openerp>
<data>
<template id="test_form">
<t t-call="website.layout">
<script type="text/javascript" src="/test_workflow/static/src/js/jquery.min.js"></script>
<body>
<div class="container">
<div class="page">
<div class="row">
<form>
<input type="date" name="start_date"/>
<input type="checkbox" name="critical" value="Critical"></input>
<input type="checkbox" name="minor" value="Minor"></input>
<input type="submit" value="Submit" ></input>
</form>
</div>
</div>
</div>
</body>
</t>
</template>
</data>
</openerp>
controller.py
class test_controller(http.Controller):
#http.route('/test1/<self_id>', auth='user', website=True)
def test1(self,self_id,**kw):
print('>>>>>>>>>>>>>>test123', kw)
return http.request.render('test_workflow.test_form', {
'num_list':[1,2,3,4,5,6,7],
})
reference: http://learnopenerp.blogspot.com/2018/06/odoo-get-web-form-template-value-in-controller.html
Is it possible to do something like this:
<field:text id="foo" label="Foo Label" model="model.foo" placeholder="foo" />
which would be compiled to:
<div class="control-group">
<label class="control-label" for="foo">Foo Label</label>
<div class="controls">
<input type="text" id="foo" placeholder="foo" ng-model="model.foo">
</div>
</div>
I tried to make a example, but Plunker wouldn't let me save my example... uploaded it to dropbox: https://dl.dropbox.com/u/2862814/plunk.zip
The example breaks with stuff like ng-change. This is due the compilation of the ng-change directive. I tried it with a high priority to the fieldText directive, but doesn't fix it.
You were pretty close with in your example, but you have to put ng-change on the input-field in the template. Your old code:
<field:text ng-change="updateHidden()" ...
Change this to
<field:text change="updateHidden()" ...
and in the directive (see http://docs.angularjs.org/guide/directive - & or &attr - provides a way to execute an expression in the context of the parent scope.)
{scope:{change:'&' ...
and finally the directive template
<input ng-change="change()" ...
Here is a modiefied and working plunkr: http://plnkr.co/edit/QmQjGQQBRtDmkCka0dul?p=preview
<field:text id="too" label="Too" model="model.too" placeholder="too" change="updateHidden()"></field:text>
<script type="text/ng-template" id="/tpl.html">
<div class="control-group">
<label class="control-label" for="{{id}}">{{label}}</label>
<div class="controls">
<input ng-change="change()" type="text" id="{{id}}" placeholder="{{placeholder}}"
ng-model="model">
</div>
</div>
</script>
directive('fieldText',function(){
return {
restrict:'E',
templateUrl:'/tpl.html',
scope:{change:'&',id:'#',model:'=',placeholder:'#',label:'#'}
}
})
I'm just wondering what the general pattern for validating forms in EmberJS? For my App.IndexView I have a form and when you click the submit button the target set to the view so I can do some validation. This works great up to the point where I need to do something with the fields that have errors. I would like to just add a class to the fields with errors but not really sure how to do it. Should the IndexView validate the form or should I create a view for each field that validates its self on blur? Below is what I have in my IndexView.
App.IndexView = Ember.View.extend
create: (model) ->
valid = #_validate model
if valid is true
#get('controller').send 'createUser'
else
# HANDLE THE FIELDS WITH ERRORS
_validate: (model) ->
invalid = []
validations = {
firstName: #_validateString model.get 'firstName'
lastName: #_validateString model.get 'lastName'
email: #_validateEmail model.get 'email'
password: #_validatePassword model.get 'password'
accountType: #_validateString model.get 'accountType'
}
# This will get all of the values then runs uniq to see if the
# form is valid
validForm = _.chain(validations).values().uniq().value()
if validForm.length is 1 and validForm[0]
true
else
# other wise build up an array of the fields with issues
for field, val of validations
if val is false
invalid.push field
invalid
_validateString: (str) ->
return false unless str
if str isnt '' then true else false
_validateEmail: (str) ->
pattern = /^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
pattern.test str
_validatePassword: (str) ->
return false unless str
if str.length >= 6 then true else false
and the template
<div class="row">
<div class="span12">
<div class="signup">
<form class="form-horizontal offset3">
<div class="control-group">
<label class="control-label" for="first_name">First Name</label>
<div class="controls">
{{ view Ember.TextField placeholder="First Name" required="true" valueBinding='firstName' name='first_name' viewName='firstNameField'}}
</div>
</div>
<div class="control-group">
<label class="control-label" for="last_name">Last Name</label>
<div class="controls">
{{ view Ember.TextField placeholder="Last Name" required="true" valueBinding='lastName' name='last_name' viewName='lastNameField'}}
</div>
</div>
<div class="control-group">
<label class="control-label" for="email">Email</label>
<div class="controls">
{{ view Ember.TextField placeholder="Email" required="true" type="email" valueBinding='email' name='email' viewName='emailField'}}
</div>
</div>
<div class="control-group">
<label class="control-label" for="password">Password</label>
<div class="controls">
{{ view Ember.TextField placeholder="Password" required="true" type="password" valueBinding='password' name='password' viewName='passwordField'}}
</div>
</div>
<div class="control-group">
<label class="control-label" for="">Account Type</label>
<div class="controls">
{{#view Ember.RadioButtonGroup name="accountType" required="true" valueBinding="accountType"}}
<label class="radio">
{{view RadioButton checked='false' value="landlord"}}
Landlord
</label>
<label class="radio">
{{view RadioButton checked='false' required="true" value="tenant"}}
Tenant
</label>
{{/view}}
</div>
</div>
<div class="control-group">
<div class="controls">
<input class="btn btn-primary" {{action create model target='view' }} type="submit" value="Sign Up">
</div>
</div>
</form>
</div>
</div>
</div>
I'm just wondering what the general pattern for validating forms in EmberJS?
There seem to be several patterns in use. It depends quite a bit on what is being validated, with the general strategy being to keep business logic far from the view layer as possible. Here are some links that may prove useful:
validations-in-emberjs-application.html recommends performing validation at the controller level, with views are used to trigger validation when focus changes. This screencast demonstrates how this pattern can be used to validate a few simple form-fields.
Asynchronous-Form-Field-Validation-With-Ember provides a few reusable components that can be used to perform simple validations at the view layer.
ember-validations is a library that can be used to add active-record style validation capabilities to any ember-object
For my App.IndexView I have a form and when you click the submit button the target set to the view so I can do some validation. This works great up to the point where I need to do something with the fields that have errors. I would like to just add a class to the field of erro but not really sure how to do it.
since you're looking to validate a number of fields at once it might make more sense to move this validation logic into the controller. Either way, typically you would bind class attributes for a given field to a property as follows:
<div class="controls" {{bindAttr class=firstNameError:error:success}}>
{{ view Ember.TextField placeholder="First Name" required="true" valueBinding='firstName' name='first_name' viewName='firstNameField'}}
</div>
So with this in place add a firstNameError property that returns true/false depending on results of your validation. Given your implementation it would probably make sense to set this property when _validate is run, but it could also be a computed property that performs validation in real-time.
Should the IndexView validate the form or should I create a view for each field that validates its self on blur?
That really depends on what you want the user experience to be like. FWIW my vote is to go with on-blur.