How can I port a bound date input helper to HTMLBars? - ember.js

I'm trying to port a 'DateInputView' TextField extension with a bound helper to HTMLBars. It appears that 'call()' has been removed from 'Handlebars.helpers.view' so the helper doesn't work anymore. I've tried several syntax changes based on forums I've read but nothing works. The field is a datepicker which switches to the native calendar picker when using a mobile device. I see an example where the bound helper is integrated into the view helper code, so uses one js file rather than two, so am trying to go that route now. Code is below. If anyone who knows to to rework it for HTMLBars please let me know.
// ../templates/avail/navigation.hbs
{{date-input id="checkin" valueBinding="controllers.avail.arrival" class="form-control date-picker"}}
// ../views/date-input.js
var DateInputView = Ember.TextField.extend({
didInsertElement: function(){
Ember.run.scheduleOnce('afterRender', this, this._setupDateInput);
},
_setupDateInput: function(){
var _this = this;
var type = Ember.$(this.get('element')).attr('type');
// Set up Date Picker for object
if( type === "input" ) {
Ember.$(this.get('element')).datepicker({
format: "yyyy-mm-dd",
autoclose: true
});
}
}
});
export default DateInputView;
// ../helpers/date-input.js
import DateInputView from '../views/date-input';
export default Ember.Handlebars.makeBoundHelper(function(options) {
Ember.assert('You can only pass attributes to the `input` helper, not arguments', arguments.length < 2);
var hash = options.hash,
types = options.hashTypes,
inputType = hash.type,
onEvent = hash.on;
delete hash.type;
delete hash.on;
hash.type = "input";
if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
hash.type = "date";
}
hash.onEvent = onEvent || 'enter';
return Ember.Handlebars.helpers.view.call(this, DateInputView, options);
});

I wound up re-working this viewHelper as a Component.

Related

View doesn't update after pushing new POJO ember

I've always read that Ember works just fine with POJOs in place of Ember Data, but now that I'm giving it a shot, I'm having a little trouble.
I'm creating an app using NW.js and LinvoDB for the database. Fetching from the DB is easy and works great:
// route/index
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
var gui = require('nw.gui');
var linvoDB = require('linvodb3');
linvoDB.defaults.store = {db: require('medeadown')};
linvoDB.dbPath = gui.App.dataPath;
var File = new linvoDB('file', {} );
var Tags = new linvoDB('tag', {});
var media = new Promise(function(resolve, reject) {
var query = File.find().sort({ctime: -1}).live();
File.on('liveQueryUpdate', function() {
resolve(query.res);
});
});
var tags = new Promise(function(resolve, reject) {
var query = Tags.find().sort({name: 1}).live();
Tags.on('liveQueryUpdate', function() {
resolve(query.res);
});
});
return Ember.RSVP.hash({
media: media,
tags: tags
});
}
});
I have a simple event set up to create a tag, save it and push it into the model:
//controllers/index
actions: {
viewMedia: function(media) {
this.transitionToRoute('media', media)
},
addTag: function() {
var linvoDB = require('linvodb3');
var gui = require('nw.gui');
linvoDB.defaults.store = {db: require('medeadown')};
linvoDB.dbPath = gui.App.dataPath;
var Tag = new linvoDB('tag', {});
var tag = new Tag();
tag.name = this.get('tagName');
tag.save();
this.get('model.tags').push(tag);
}
}
I can verify that the tag object is being inserted correctly in the the tag array in the model, but the view isn't updating. From what I've read, that's cause I'm not using Ember.Object.
How are you suppose to do this with POJOs or do I have to use Ember.Objects? Thanks.
Ember provides it's own array implementation in Ember.Array/Ember.MutableArray that adds a lot of nifty things, like being properly observable in the Ember ecosystem. The Ember.MutableArray in particular (or rather Ember.MutableEnumerable if you want to go deep) has a method called pushObject(obj) that Push the object onto the end of the array. and also notifies any subscribers.
Since Ember also is nice enough to add these to the regular Arrays prototype to make it easy for people to get going, you should be able to simply do this.get('model.tags').pushObject(tag); in your code.

TodoMVC with ember, id does not increment

I am following the getting started guide from emberjs, and am at the point where I can add todos. My problem is though that when I add a todo it has an id value of null - is there a practical way to auto increment this?
var TodosController = Ember.ArrayController.extend({
actions: {
createTodo: function() {
var title = this.get('newTitle');
if (!title.trim()) {
return;
}
var todo = this.store.createRecord('todo', {
title: title,
isCompleted: false
});
this.set('newTitle', '');
todo.save();
}
}
});
When you call this.store.createRecord() you have an "option" to have an id autogenerated (see here) Ultimately though, that responsibility is delegated to an adapter. If your adapter has generateIdForRecord() method - this will be used to create an id. So, for example, FixtureAdapter implements this method as follows (see here):
generateIdForRecord: function(store) {
return "fixture-" + counter++;
}
ember-data uses RestAdapter by default (see here), so you would need to add the method for the id to be generated on the client...

how to remove Attachment for specific model in openrp?

I'm developing my own model. I installed Document model. This model is giving attachment button on top of the form. but i want this attachment button in only my module. I want to hide other that button in other form (other model).
so I'm getting following code for removing "create and save" for specific model. but this coding is not working my side. please tell me how to use attachment button for specific model? and how to hide other models?.
openerp.web_smile_hide_buttons = function(openerp) {
// Models for which we'll hide create and duplicate buttons
var MODELS_TO_HIDE = ['kit.lab'];
// Hide the create button on all list views, which affect tree views and many2one pop-up search view
openerp.web.ListView.include({
start: function() {
var self = this;
var ret = this._super.apply(this, arguments);
var res_model = this.dataset.model;
if ($.inArray(res_model, MODELS_TO_HIDE) != -1) {
self.options.addable = false;
};
return ret;
},
});
// Hide the save button on form views
openerp.web.FormView.include({
on_loaded: function(data) {
var self = this;
var ret = this._super.apply(this, arguments);
var res_model = this.dataset.model;
// if ($.inArray(res_model, MODELS_TO_HIDE) != -1) {
this.$element.find('button.oe_dropdown_toggle.oe_dropdown_arrow').remove();
this.$element.find('button.oe_form_button_save').remove();
//};
return ret;
},
});
// Hide the create and duplicate button on all page views (i.e. read-only form views)
openerp.web.PageView.include({
on_loaded: function(data) {
var self = this;
var ret = this._super.apply(this, arguments);
var res_model = this.dataset.model;
if ($.inArray(res_model, MODELS_TO_HIDE) != -1) {
this.$element.find('button.oe_form_button_create').remove();
this.$element.find('button.oe_form_button_duplicate').remove();
};
return ret;
},
});
};
This question is older, but I had the same problem and figured it out. Its most likely not the best solution, but it works. I assume you know how to write a custom module, so just add a dependency to "document" and create an own javascript (e.g. static/src/js/document.js, don't forget to include it in your openerp.py) with the following content:
openerp.document = function (instance) {
_t = instance.web._t;
instance.web.Sidebar.include({
init : function(){
this._super.apply(this, arguments);
if (window.location.href.indexOf('&model=res.partner') === -1)
this.sections.splice(1, 0, { 'name' : 'files', 'label' : _t('Attachment(s)'), });
this.items['files'] = [];
},
});
};
In this example the "Attachment" button will be hidden in the res.partner form view.
Maybe someone else knows a better way to look for the current model compared to my solution to look for the string in window.location.href

How to order addEventlistener in Ember. Want to execute my eventListener before 3rd party on same element

Hi I am trying to do things with emberjs and google maps.
The issue with google autocomplete api is if user enters text in location search but does not select any value from dropdown suggestion in textbox the first suggestion is not selected. I found a good solution for it on stack overflow solutiion in jquery only
I am trying to do it in ember.
App.AutocompleteAddressView = Ember.TextField.extend({
tagName: 'input',
autocomplete: null,
didInsertElement: function () {
this._super();
var options = {
componentRestrictions: {
country: "xx"
}
};
this.set('autocomplete', new google.maps.places.Autocomplete(this.$()[0], options));
//var autocomplete = new google.maps.places.Autocomplete(this.$()[0], options);
},
keyDown: function (e) {
var that = this;
var suggestion_selected = $(".pac-item.pac-selected").length > 0;
if (e.keyCode === 13 && !suggestion_selected) {
//key down arrow simulations
var event = Ember.$.Event('keypress', {
keyCode: 40
});
Ember.run(this.$("#searchTextField"), 'trigger', event);
console.log('loggin autocomplete');
console.log(this.get('autocomplete'));
//adding google map event and then triggering it
google.maps.event.addListener(this.get('autocomplete'), 'place_changed', function () {
var place = that.get('autocomplete').getPlace();
that.set('autocomplete_result', place)
console.log('google event was triggered');
console.log(that.get('autocomplete_result'));
});
google.maps.event.trigger(this.get('autocomplete'), 'place_changed');
}
}
});
Now I need to do simulation part. I guess ember testing has somthing that simulates keypress but I cannot used it.
If I use the solution from the link I mentioned things work fine first time but on clicking browser back navigation it does not work.
The solution I tried in code not working

return value from computed properties callback did not update templates

Sorry for the long title. Its quite hard to put into words.
Ember version: 1.2.0
here goes:
My components:
App.AutocompleteComponent = Ember.Component.extend({
searchResults: function() {
var returnValue
var service = new google.maps.places.AutocompleteService();
service.getPlacePredictions({options},callback);
function callback(results){
returnValue = results;
}
return returnValue;
}.property('searchText')
My Templates:
{{input type="text" value=searchText placeholder="Search..."}}
<ul >
{{#each itemResults}}
<li>{{this.name}}</li>
{{/each}}
</ul>
When i debug using ember chrome debug tool, i can see the component holding the searchResults values correctly. But it is not being updated accordingly in the template.
Any ideas?
if this way of handling/using computed property is not suggested, can suggest any other ways?
Thank you in advance.
You probably want to debounce this (and I don't know what options is, is it a global var?). And the template is itemResults instead of searchResults. http://emberjs.com/api/classes/Ember.run.html#method_debounce
watchSearchResults: function() {
var self = this;
var service = new google.maps.places.AutocompleteService();
var callback= function(results){
self.set('searchResults', results);
}
service.getPlacePredictions({options},callback);
}.observes('searchText')
Thank you kingpin2k for your response,
I have found other way of dealing with returns that obviously didn't work on callbacks and since computed property which in a way requires 'returns' making it not feasible on this use case.
Instead i have opt to using Observers.
By the way, this code is was meant to be dealing with auto complete.
here is the final code:
WebClient.AutocompleteFromComponent = Ember.Component.extend({
searchTextChanged: Em.observer('searchText',function(){
var service = new google.maps.places.AutocompleteService();
service.getPlacePredictions({
input: this.get('searchText'),
types: ['(regions)'],
componentRestrictions: {
country: 'my'
}
}, function(predictions, status) {
//Start callback function
if (status != google.maps.places.PlacesServiceStatus.OK) {
alert(status);
return;
}
for (var i = 0, prediction; prediction = predictions[i]; i++) {
console.log(prediction.description);
mapItem = {};
mapItem.name = prediction.description;
mapItem.type = 'map'
mapItem.reference = prediction.reference;
itemResults.push(mapItem);
}
//console.log(itemResults)
self.set('itemResults', itemResults)
});
})
The template code is still the same.