stefanpenner / ember-app-kit

deprecated: see https://github.com/stefanpenner/ember-cli
MIT License
1.02k stars 231 forks source link

How to Ember.TextField.extend #343

Closed hashg closed 10 years ago

hashg commented 10 years ago

I am using two js libraries - chosen and pikaday (I found some code in blogs where commuity has shared how to integrate with Ember). I defined the them this way in previous EAK. It worked untill yesterday, when I migrated to new EAK.

In app.js - CalendarDatePicker repo:

App.CalendarDatePicker = Ember.TextField.extend({
  _picker: null,

  modelChangedValue: function(){
    var picker = this.get("_picker");
    if (picker){
      picker.setDate(this.get("value"));
    }
  }.observes("value"),

  didInsertElement: function(){
    var currentYear = (new Date()).getFullYear();
    var formElement = this.$()[0];
    var picker = new Pikaday({
      field: formElement,
      format: 'MM/DD/YYYY',
      yearRange: [currentYear-3,currentYear+3]
    });
    this.set("_picker", picker);
  },

  willDestroyElement: function(){
    var picker = this.get("_picker");
    if (picker) {
      picker.destroy();
    }
    this.set("_picker", null);
  }
});

In templates it is used (repo): {{view App.CalendarDatePicker class="form-control input-lg" valueBinding="from_dt"}}

In app.js - Chosen repo:

App.Chosen = Ember.Select.extend({
  multiple: false,
  width: '100%',
  disableSearchThreshold: 1,
  searchContains: true,
  attributeBindings:['multiple', 'width', 'disableSearchThreshold', 'searchContains', 'autofocus'],

  didInsertElement: function(){
    this._super();

    var options = {
      multiple: this.get('multiple'),
      width: this.get('width'),
      disable_search_threshold: this.get('disableSearchThreshold'),
      search_contains: this.get('searchContains')
    };

    options.clean_search_text = this.cleanSearchText;
    options.calling_context = this;

    if(this.get('multiple')){
      options.placeholder_text_multiple = this.get('prompt');
    } else {
      options.placeholder_text_single = this.get('prompt');
    }

    this.$().chosen(options);

    // observes for new changes on options to trigger an update on Chosen
    return this.addObserver(this.get("optionLabelPath").replace(/^content/, "content.@each"), function() {
      return this.rerenderChosen();
    });

  },

  _closeChosen: function(){
    // trigger escape to close chosen
    this.$().next('.chosen-container-active').find('input').trigger({type:'keyup', which:27});
  },

  cleanSearchText: function(option, context){
    return option.text;
  },

  rerenderChosen: function(){
    // Don't trigger Chosen update until after DOM elements have finished rendering.
    Ember.run.schedule('afterRender', this, function(){
      this.$().trigger('chosen:updated');
    });
  }

});

In templates it is used as (repo): {{view App.Chosen content=members value=member optionLabelPath="content.firstname" optionValuePath="content.id" autofocus=true}}

After migrating to latest EAK. I get following errors, when I traverse to route containing these tags. This ERRORS are thrown:

Assertion failed: Unable to find view at path 'App.CalendarDatePicker' ember.js:3231
Assertion failed: You must pass a view to the #view helper, not App.CalendarDatePicker () ember.js:3231
Uncaught TypeError: Cannot read property 'proto' of undefined ember.js:26367
Assertion failed: Unable to find view at path 'App.CalendarDatePicker' ember.js:3231
Assertion failed: You must pass a view to the #view helper, not App.CalendarDatePicker () ember.js:3231
Uncaught TypeError: Cannot read property 'proto' of undefined ember.js:26367
stefanpenner commented 10 years ago

in eak you should basically never reference globals.

{{view 'chosen'}} will look up app/views/choosen.js

within app/views/choosen.js:

export default Ember.Select.extend({
  //..codez
});
mehulkar commented 10 years ago

@stefanpenner along the same lines, what would be the right way to create a custom object in some controller, for example?

// at app/models/track.js
var Track = Ember.Object.extend();
export default Track;

// at app/controllers/something
var SomethingController = Ember.Controller.extend({
  actions: {
    makeTrack: function() {
      return App.Track.create();
    }
  }
})

export default SomethingController;

How do I avoid referencing the App global here?

rwjblue commented 10 years ago

@mehulkar You would do something like:

import Track from 'appkit/models/track';

var track = Track.create();
mehulkar commented 10 years ago

awesome. Thanks. Going to take some time to read up on es6 syntax today. Not sure I really understand what's going on.

assimovt commented 10 years ago

Oops, I am having the same issue. @stefanpenner I tried what you suggested, but didn't work. What am I doing wrong here? Thx

# views/file.coffee

File = Ember.TextField.extend(
  tagName: "input"
  attributeBindings: ["name"]
  type: "file"
  file: null
  change: (e) ->
    reader = undefined
    that = undefined
    reader = new FileReader()
    that = this
    reader.onload = (e) ->
      fileToUpload = undefined
      fileToUpload = e.srcElement.result
      Ember.run ->
        that.set "file", fileToUpload

    reader.readAsText e.target.files[0]
)

`export default File`

And then in template:

<div class="avatar">
  {{view "file" name="image" file=image }}
</div>

Trying to work with this example: http://jsfiddle.net/marciojunior/LxEsF/