2013-08-18 30 views
2

我正在爲世界時間的應用程序工作。我有一個餘燼模型:Clock
我想更新每秒鐘的time屬性。Ember.js:如何從視圖中調用模型中定義的方法?

現在,我已經在時鐘中定義了一個start方法,它負責更新時鐘模型的時間屬性。

我對此有兩個問題: 1.如何從我的視圖中調用start模型的方法 2.有沒有更好的方法可以使用?

這裏是我的模型,視圖,控制器,路由器和模板(櫃面你有興趣):

型號:

App.Clock = DS.Model.extend({ 
    city: DS.attr('string'), 
    country: DS.attr('string'), 
    latitude: DS.attr('string'), 
    longitude: DS.attr('string'), 
    time: DS.attr('date'), 
    order: DS.attr('number'), 

    start: function() { 
     var clock = this; 

     var updateTime = function() { 
      var timezoneService = Utilities.TimezoneService; 

      timezoneService.getTimezone(clock.get('latitude'), clock.get('longitude'), function(timezone) { 
       clock.set('time', timezoneService.getDateTime(timezone.offset)); 
      }); 
     }; 

     updateTime(); 

     window.setInterval(function() { 
      updateTime(); 
     }, 1000); 
    } 
}); 

瀏覽:

App.ClocksView = Ember.View.extend({ 
    templateName : 'world_clock/clocks' 
}); 

App.ClocksNewView = Ember.View.extend({ 
    templateName : 'world_clock/new' 
}); 

控制器:

App.ClocksController = Ember.ArrayController.extend({ 
    sortProperties: ['order'] 
}); 

App.ClocksNewController = Ember.ObjectController.extend({ 
    city: null, 
    save: function() { 
     var cityName = this.get('city'); 
     if(!cityName.trim()){ 
      return; 
     } 

     var locationService = Utilities.LocationService.getInstance(); 

     locationService.lookupLocation(cityName, function(location) { 
      var city = location.city; 
      var country = location.country; 
      var lat = location.latitude; 
      var lon = location.longitude; 

      if(city && country && lat && lon) { 
       var clks = App.Clock.find({ city: city }); 
       clks.on('didLoad', function() { 
        if(clks.get('length') === 0) { 
         var clock = App.Clock.createRecord({ 
          city: location.city, 
          country: location.country, 
          latitude: location.latitude, 
          longitude: location.longitude, 
          order: 10 
         }); 

         clock.save(); 
        } 
       }); 
      } 
     }); 

     this.set('city', ''); 

     this.get('target').transitionTo('clocks'); 
    } 
}); 

路由器:

App.Router.map(function() { 
    this.resource('clocks', { path: '/' }, function() { 
     this.route('new'); 
    }); 
}); 

App.ClocksRoute = Ember.Route.extend({ 
    model: function() { 
     var locationService = Utilities.LocationService.getInstance(); 

     locationService.getLocation(function(location) { 
      App.Clock.createRecord({ 
       city: location.city, 
       country: location.country, 
       latitude: location.latitude, 
       longitude: location.longitude, 
       order: -10 
      }); 
     }); 

     return App.Clock.find(); 
    } 
}); 

clocks.handlebars:

{{outlet}} 
{{#linkTo "clocks.new"}}Add Clock{{/linkTo}} 
<ul> 
    {{#each controller}} 
    <li>{{city}}, {{country}} - {{time}}</li> 
    {{else}} 
    You have not defined any clock yet. 
    {{/each}} 
</ul> 

new.handlebars:

<form {{action "save" on="submit"}}> 
    {{view Ember.TextField valueBinding="city" placeholder="City"}} 
    <button>Save</button> 
</form> 

回答

3

How can I call the start method of the model from my view

除少數情況下,從視圖中調用模型方法不是一個好主意。這說這是可能的。例如,你可以使用這樣的didInsertElement:

{{each controller itemViewClass="App.ClockView" emptyViewClass="App.NoClocksView"}} 

App.ClockView = Ember.View.extend({ 
    template: Ember.Handlebars.compile("<li>{{city}}, {{country}} - {{time}}</li>"), 
    didInsertElement: function() { 
    var clock = this.get('content'); 
    clock.start(); 
    } 
}); 

App.NoClocksView = Ember.View.extend({ 
    template: Ember.Handlebars.compile("You have not defined any clock yet.") 
}); 

問題這種方法是,它有點打破封裝,這意味着很多微妙的東西可能會出問題。例如,如果ember重新使用視圖,所以它有一個新的時鐘,但didInsertElement不運行。這就是爲什麼Initializing State in didInsertElement不是一個好主意。或者,如果用戶導航到/來自該路線,那麼模型時鐘將在後臺運行,然後當用戶回來時他們都會重新開始。這使我:

Is there any better approach I can take?

也許time不應該的App.Clock的屬性。這不像你想要在數據庫中節省時間,對吧?一種選擇是: - 給App.Clock時區的一個computedProperty偏移 - 一個currentTime屬性添加到clocksController - 當ClocksView已經插入,使用的setTimeout刷新currentTime的每一秒 - 使一個組件(世界時鐘),這使得特定時鐘 - 將計算出的屬性time添加到世界時鐘,該世界時鐘根據currentTime和時鐘的時區偏移量計算時間。

因此,像這樣:

<script type="text/x-handlebars" id="clocks"> 
{{outlet}} 
{{#linkTo "clocks.new"}}Add Clock{{/linkTo}} 
<ul> 
{{#each clock in controller}} 
<li> 
{{world-clock city="clock.city" country="clock.country" offset="clock.offset" currentTime="currentTime"}} 
</li> 
{{/each}} 
</ul> 
</script> 

<script type="text/x-handlebars" id="components/world-clock"> 
    {{city}}, {{country}} - {{time}} 
</script> 

App.Clock = DS.Model.extend({ 
    city: DS.attr('string'), 
    country: DS.attr('string'), 
    latitude: DS.attr('string'), 
    longitude: DS.attr('string'), 
    order: DS.attr('number'), 
    offset: function() { 
    var offset; 
    var service = Utilities.TimezoneService; 
    service.getTimezone(this.get('latitude'), this.get('longitude'), function(zone) { 
     offset = timezone.offset 
    }); 
    return offset; 
    }.property('latitude', 'longitude') 
}); 

App.WorldClockComponent = Ember.Component.extend({ 
    tagName: 'li', 
    time: function() { 
    var service = Utilities.TimezoneService; 
    return service.getDateTime(this.get('offset')); 
    }.property('offset', 'currentTime'); 
}); 
+0

非常感謝非常詳細的答覆:)我唯一的問題是,既然'TimeZoneService.getTimezone'是異步回調,也不會偏移值將始終保持爲空? – Moon

+1

是的,這是一個很好的觀點。猜測時鐘應該有'positionDidChange'這樣的觀察者,每當經緯度發生變化時就會觸發。該觀察者會調用時區服務並設置偏移屬性。 –

+0

有道理。但是現在我還有幾個問題。 [1]我在'Rails Mountable Engine'中構建這個應用程序。出於這個原因,'{{world-clock city =「clock.city」...'工作不正常。我怎樣才能定義組件的模板路徑? [2]'{{#每個時鐘在控制器}}'不工作,但'{{#每個控制器}}'。你可以向我解釋這件事嗎? [3]你能爲我提供控制器的示例代碼嗎? – Moon

相關問題