Masking Phone in Ember JS - ember.js

I am trying to mask a Phone number in a input field, can somebody please help me in this regards. Here is my code for the html (or .hbs file)
<label class="control-label">Phone</label>
{{masked-input mask='(999) 999-9999'
value=model.Address.Phone
input-format='regex'
input-filter='\(*[0-9]{3}\) [0-9]{3}-[0-9]{4}'
input-filter-message='Phone number is not valid.'
class='form-control phone masked'
maxlength="14"}}
</div>
And my component definition is as below:
export default () => {
IMS.registerComponent("masked-input", {
tagName: 'input',
attrParams: ['required', 'title', 'name', 'placeholder'],
loaded: false,
prop: Ember.observer(
'required',
'title',
'name',
'placeholder',
'value',
function () {
var scope = this;
$(this.element).val(Ember.get(scope, 'value'));
var stamp = new Date();
if (Ember.get(scope, 'loaded') == true) {
var element = $(this.element);
var attrs = Ember.get(this, 'attrParams');
attrs.forEach(function (attr) {
var value = Ember.get(scope, attr);
if (value == '' | value == null) {
element.removeAttr(attr);
} else {
element.attr(attr, value);
}
})
}
}),
observeMask: Ember.observer('mask', function () {
var scope = this;
$(this.element).inputmask({
mask: Ember.get(scope, 'mask')
});
}),
didInsertElement: function () {
var scope = this;
setTimeout(function () {
var value = Ember.get(scope, 'value');
var element = $(scope.element);
var change = function () { Ember.set(scope, 'value', element.val()); }
element.val(Ember.get(scope, 'value'));
element.attr('type', 'text');
element.change(change);
Ember.set(scope, 'loaded', true);
scope.observeChanges();
element.inputmask({
mask: Ember.get(scope, 'mask')
});
element.attr('input-format', Ember.get(scope, 'input-format'));
element.attr('input-filter', Ember.get(scope, 'input-filter'));
element.attr('input-filter-message', Ember.get(scope, 'input-filter-message'));
}, 250);
}
})
}

Related

The changed value is not reflecting on the input field in ReactJS, TestUtils

I am using ReactJs and Mocha and trying few unit tests. I have two mandatory form fields First Name and Last Name. I am trying to test the validation where if only one field is entered, the other field displays the missing value validation error.
Below code simulates the changes to the value and simulates the form submit.
TestUtils.Simulate.change(firstNameElement , {target: {value: 'Joe'}});
TestUtils.Simulate.submit(formElement)
The changed value is reflected in the event handlers on First Name. But, not in the test. So, both the fields display missing value validation failing my test.
What I could be doing wrong here?
Below are code:
//NameForm.jsx
'use strict';
var React=require('react')
var forms = require('newforms')
var NameForm = forms.Form.extend({
firstName: forms.CharField({maxLength: 100, label: "First name(s)"}),
lastName: forms.CharField({maxLength: 100, label: "Last name"}),
cleanFirstName(callback) {
callback(null)
},
render() {
return this.boundFields().map(bf => {
return <div className={'form-group ' + bf.status()}>
<label className="form-label" htmlFor={bf.name}>
<span className="form-label-bold">{bf.label}</span>
</label>
{bf.errors().messages().map(message => <span className="error-message">{message}</span>)}
<input className="form-control" id={bf.name} type="text" name={bf.name} onChange = {this.onChangeHandler}/>
</div>
})
}
, onChangeHandler: function(e){
console.log("onchnage on input is called ----- >> " + e.target.value)
}
})
module.exports = {
NameForm
}
Here is NamePage.jsx:
'use strict';
var React = require('react')
var {ErrorObject} = require('newforms')
var superagent = require('superagent-ls')
var {API_URL} = require('../../constants')
var {NameForm} = require('./NameForm')
var NamePage = React.createClass({
contextTypes: {
router: React.PropTypes.func.isRequired
},
propTypes: {
data: React.PropTypes.object,
errors: React.PropTypes.object
},
statics: {
title: 'Name',
willTransitionTo(transition, params, query, cb, req) {
if (req.method != 'POST') { return cb() }
superagent.post(`${API_URL}/form/NameForm`).send(req.body).withCredentials().end((err, res) => {
if (err || res.serverError) {
return cb(err || new Error(`Server error: ${res.body}`))
}
if (res.clientError) {
transition.redirect('name', {}, {}, {
data: req.body,
errors: res.body
})
}
else {
transition.redirect('summary')
}
cb()
})
}
},
getInitialState() {
return {
client: false,
form: new NameForm({
onChange: this.forceUpdate.bind(this),
data: this.props.data,
errors: this._getErrorObject()
})
}
},
componentDidMount() {
this.setState({client: true})
},
componentWillReceiveProps(nextProps) {
if (nextProps.errors) {
var errorObject = this._getErrorObject(nextProps.errors)
this.refs.nameForm.getForm().setErrors(errorObject)
}
},
_getErrorObject(errors) {
if (!errors) { errors = this.props.errors }
return errors ? ErrorObject.fromJSON(errors) : null
},
_onSubmit(e) {
e.preventDefault()
var form = this.state.form
form.validate(this.refs.form, (err, isValid) => {
if (isValid) {
this.context.router.transitionTo('name', {}, {}, {
method: 'POST',
body: form.data
})
}
})
},
render() {
return <div>
<h1 className="heading-large">Your name</h1>
<form action='name' method="POST" onSubmit={this._onSubmit} ref="form" autoComplete="off" noValidate={this.state.client}>
{this.state.form.render()}
<button type="submit" className="button">Next</button>
</form>
</div>
},
})
module.exports = NamePage
Here is NameTest.js :
//NameTest.js
var React = require('react')
var ReactAddons = require('react/addons')
var TestUtils = React.addons.TestUtils
var InputFieldItem = require('../../src/page/name/NamePage')
describe('Name page component', function(){
var renderedComponent;
before('render element', function() {
console.log("*** in before")
renderedComponent = TestUtils.renderIntoDocument(
<InputFieldItem />
);
});
it('Only First Name entered should display one error message', function() {
renderedComponent = TestUtils.renderIntoDocument(
<InputFieldItem />
);
var formElement = TestUtils.findRenderedDOMComponentWithTag(renderedComponent, 'form').getDOMNode()
var firstNameElement = TestUtils.scryRenderedDOMComponentsWithTag(renderedComponent, 'input')[0].getDOMNode()
var lastNameElement = TestUtils.scryRenderedDOMComponentsWithTag(renderedComponent, 'input')[1].getDOMNode()
var buttonElement = TestUtils.findRenderedDOMComponentWithTag(renderedComponent, 'button').getDOMNode()
TestUtils.Simulate.change(firstNameElement , {target: {value: 'Joe'}});
TestUtils.Simulate.submit(formElement)
var errorSpans = TestUtils.scryRenderedDOMComponentsWithClass(renderedComponent, 'error-message')
console.log("First name value is :|"+ firstNameElement.value + "|")
expect (errorSpans.length).to.equal(1)
})
});

Ember nested array property observable

When setting property observable on a nested array in ember my property isn't notified.
size: function(){
var result = "no size";
this.get('data.properties').forEach(function (g) {
if (g.group == "style") {
g.items.forEach(function (p) {
if (p.id == 'size') result = p.computedValue();
});
}
});
console.log(result);
return result;
}.property('data.properties.#each.items.#each.value')
In this SO accepted answer : https://stackoverflow.com/a/9381152/2068563
it says that this should work.
But for me the propurty is only computed at init.
here is the fiddle: http://jsfiddle.net/jmorvan/eVWfj/
Any ideas?
Ok so, the solution is to link computed properties updated by observable to bubble up the event like this:
App.groupObj = Ember.Object.extend({
group: "style",
name: "Style",
_changed: 0,
changed: function (key, value) {
if (value) {
this.set('_changed', value);
}
return this.get('_changed');
}.property(),
itemChanged: function () {
this.set('changed', +new Date());
console.log('item changed!');
}.observes('items.#each.val'),
items: []
});
App.itemObj = Ember.Object.extend({
_val: 6,
id: null,
name: null,
group: null,
fieldType: null,
val: function (key, value) {
if (value) {
this.set('_val', value);
}
return this.get('_val');
}.property(),
computedValue: function () {
return this.val;
}
});
Basically, the grouo object listens to any action on the item's val property and updates his own changed property. this way i can do:
size: function(){
var result = "no size";
this.get('data.properties').forEach(function (g) {
if (g.group == "style") {
g.items.forEach(function (p) {
if (p.id == 'size') result = p.computedValue();
});
}
});
console.log(result);
return result;
}.property('data.properties.#each.changed')
I guess my first miastake was to think ember was magically going to pickup changes on my nested objects.
I also thought that linking computed properties would work, which obviously didnt! (Why?)
the updated fiddle: http://jsfiddle.net/jmorvan/LEyCD/
EDIT
Since this was pretty long to implement on each object I created my own object with observable based on a selector.
App.changeAwareArray = Ember.ArrayProxy.extend({
init: function () {
this.set('content', []);
this._super();
if (!this.get('changeSelector')) this.set('changeSelector', '_changed');
this.addObserver('content.#each.' + this.get('changeSelector'), this.handleChange);
},
_changed: null,
handleChange: function () {
this.set('_changed', +new Date());
}
});
App.changeAwareObject = Ember.Object.extend({
init: function () {
this._super();
if (!this.get('changeSelector')) this.set('changeSelector', '_changed');
this.addObserver(this.get('changeSelector'), this.handleChange);
},
_changed: null,
changed: function (key, value) {
if (value) {
this.set('_changed', value);
}
return this.get('_changed');
}.property(),
handleChange: function () {
this.set('_changed', +new Date());
}
});
Now you can chain them to observe them:
App.groupObj = App.changeAwareObject.extend({
changeSelector:'items._changed',
group: "style",
name: "Style",
items: App.changeAwareArray.create()
});
App.itemObj = Ember.Object.extend({
_val: 6,
_changed: null,
id: null,
name: null,
group: null,
fieldType: null,
val: function (key, value) {
if (value) {
this.set('_val', value);
this.set('_changed', +new Date());
}
return this.get('_val');
}.property(),
computedValue: function () {
return this.val;
}
});
And get the data in your view/controller:
App.IndexView = Ember.View.extend({
init: function () {
this._super();
//populate the Array
this.data.properties.pushObject(createData());
},
elementId: "test",
size: function () {
var result = "no size";
this.get('data.properties').forEach(function (g) {
if (g.group == "style") {
g.items.forEach(function (p) {
if (p.id == 'size') result = p.computedValue();
});
}
});
return result;
}.property('data.properties._changed'),
offset: function () {
var result = "no offset";
this.get('data.properties').forEach(function (g) {
if (g.group == "style") {
g.items.forEach(function (p) {
if (p.id == 'offset') result = p.computedValue();
});
}
});
return result;
}.property('data.properties._changed'),
data:{
name: "base",
properties: App.changeAwareArray.create()
}
});
you can find a working fiddle here: http://jsfiddle.net/jmorvan/VRVac/

Implementation of displaying breadcrumb path in ember with sample code or may be direct me to some repository

Can some one redirect me to some project code or some working example of displaying crumble path in ember?
This code doesn't work for some reason.
ApplicationController = Ember.Controller.extend({
needs: ['breadcrumbs'],
hashChangeOccured: function(context) {
var loc = context.split('/');
var path = [];
var prev;
loc.forEach(function(it) {
if (typeof prev === 'undefined') prev = it;
else prev += ('/'+it)
path.push(Em.Object.create({ href: prev, name: it }));
});
this.get('controllers.breadcrumbs').set('content',path)
}
});
ready : function() {
$(window).on('hashchange',function() {
Ember.Instrumentation.instrument("hash.changeOccured", location.hash);
});
$(window).trigger('hashchange');
}
App.ApplicationRoute = Ember.Route.extend({
setupController: function(controller, model) {
Ember.Instrumentation.subscribe("hash.changeOccured", {
before: function(name, timestamp, payload) {
controller.send('hashChangeOccured', payload);
},
after: function() {}
});
}
});
Here you have a starting point:
APP.Breadcrumb = Em.View.extend({
classNames: ['breadcrumb'],
tagName: 'ul',
activeChanged: function () {
var self = this;
Em.run.next(this, function () {
self.set('active', self.get('childViews.firstObject.active'));
});
}.observes('childViews.firstObject.active'),
disabled: function () {
var role = this.get('role');
if (!Em.isEmpty(role)) {
return !this.get('controller.controllers.login').hasRole(role);
}
return false;
}.property("controller.controllers.login.authenticationMediator.roles.#each"),
currentPathChanged: function() {
this.rerender();
}.observes('controller.currentPath'),
template: function () {
var template = [],
controller = this.get('controller'),
router = controller.container.lookup('router:main'),
currentHandlerInfos = router.get('router.currentHandlerInfos');
for (var i = 0; i < currentHandlerInfos.length; i++) {
var name = Em.get(currentHandlerInfos[i], 'name');
if (!(router.hasRoute(name) || router.hasRoute(name + '.index')) || name.endsWith('.index')) {
continue;
}
var notLast = i < currentHandlerInfos.length - 1 && !Em.get(currentHandlerInfos[i + 1], 'name').endsWith('.index');
template.push('<li' + (notLast ? '>' : ' class="active">'));
if (notLast) {
template.push('{{#linkTo "' + name + '"}}');
}
template.push(name);
if (notLast) {
template.push('{{/linkTo}}');
}
if (notLast) {
template.push('<span class="divider">/</span>');
}
template.push('</li>');
}
return Em.Handlebars.compile(template.join("\n"));
}.property('controller.currentPath')
});

can I change rest model state without using .set()

I have model with custom attribute(array of objects). Like this
App.Adapter.registerTransform('images', {
serialize: function(value) {
var ret = []
value.forEach(function(img){
ret.pushObject(img.get('uuid'))
})
if (ret.get('length')) {
return ret.join(',')
} else
return false
},
deserialize: function(value) {
ret = []
if (typeof value !== 'undefined') {
uuids = value.split(',')
for (var i = 0; i < uuids.length; i++) {
var id = uuids[i]
ret.pushObject( App.Image.create({'uuid': id}) )
}
}
return ret
}
})
And my model.
App.Item = DS.Model.extend({
…
images: DS.attr('images')
})
in controller I need commit data, after pushing changes in this property. What I need to do for this case?
uploadImage: function(){
var self = this
uploading.done(function(result) {
self.get('images').pushObject(App.Image.create({uuid:result.uuid}))
console.log(self.get('isDirty')) // false
self.get('store').commit() //nothing to change
}).fail(function(result) {
…
}).always(function() {
…
})
},
Have you tried to do this?
self.notifyPropertyChange('images');

Controller is defined, but can not be found

When trying to get the nodeEditController from nodeController:startEditing, I get the following problem:
Uncaught TypeError: Cannot call method 'set' of undefined
This is the NodeController:
SettingsApp.NodeController = Ember.ObjectController.extend({
isEditing: false,
startEditing: function () {
debugger;
var nodeEditController = this.get('controllers.nodeEdit');
nodeEditController.set('content', this.get('content'));
nodeEditController.startEditing();
this.set('isEditing', true);
},
...
This is the NodeEditController:
SettingsApp.NodeEditController = Ember.ObjectController.extend({
needs: ['node'],
startEditing: function () {
//debugger;
// add the contact and its associated phone numbers to a local transaction
var node = this.get('content');
var transaction = node.get('store').transaction();
transaction.add(node);
// contact.get('phones').forEach(function (phone) {
// transaction.add(phone);
// });
this.transaction = transaction;
},
...
The error happens in line:
nodeEditController.set('content', this.get('content'));
Because:
var nodeEditController = this.get('controllers.nodeEdit');
Returns undefined. Why is that? The NodeEditController is defined!
The NodeController is missing the needs property:
SettingsApp.NodeController = Ember.ObjectController.extend({
needs : ["nodeEdit"],
isEditing: false,
startEditing: function () {
debugger;
var nodeEditController = this.get('controllers.nodeEdit');
nodeEditController.set('content', this.get('content'));
nodeEditController.startEditing();
this.set('isEditing', true);
},
...