Im quite new to rubymotion and Promotion so sorry if the question is a stupid one :) I can't find any information how to manipulate a height of a cell after clicking on it. Somebody knows how to do this? Thanks a lot
class TimeOffsScreen < ProMotion::TableScreen
def table_data
TimeItem.all.map do |item|
{
title: item.name,
action: :open_time_item,
arguments: { item: item },
editing_style: :delete,
height: 90
}
end
end
def open_time_item(item)
# Set height of this table cell
end
end
There isn't a great way to do this currently. One way you can accomplish it is to access the data in your hash and then refresh the table data.
By the way, I noticed a bug in your code. You need to provide an array of sections wrapping your cells.
I've put an example of how to do this here, but you'll need to verify that it does work.
def table_data
#time_items ||= TimeItem.all
[{
cells: #time_items.map do |item|
{
title: item.name,
action: :open_time_item,
arguments: { item: item },
editing_style: :delete,
height: item.height || 90
}
end
}]
end
def open_time_item(item)
item.height = 180 # .height can be a temporary attr_accessor with no persistence
update_table_data
end
Related
I have looked everywhere in the ProMotion docs and examples but I am unable to find a way to change a TableScreen layout, specifically the TableView cell's vertical starting position.
I have an UIView on the top of my screen to show some buttons, and the TableView cells should start underneath, but right now they are on top of each other.
I have even managed to move the TableView using the REPL console:
rmq(4496872960).nudge d: 10
where 4496872960 is the id of my UITableViewWrapperView object, but I have no idea where to put the layout coordinates for this object in code.
My screen code:
class HomeScreen < PM::TableScreen
title I18n.t("home_screen.title")
tab_bar_item title: I18n.t("home_screen.title"), item: "icon-home_32x32.png"
row_height :auto, estimated: 30
stylesheet HomeScreenStylesheet
def on_load
#matches = [{attributes: {status: "dummy1", player2: {email: "dummy1#match.com"}}},{attributes: {status: "dummy2", player2: {email: "dummy2#match.com"}}}]
append(TopHomeView, :top_home_view)
set_nav_bar_button :left, title: I18n.t("home_screen.sign_out_label"), image: image.resource("icon-logout-32x32.png"), action: :sign_out
set_nav_bar_button :right, title: (Auth.current_user ? Auth.current_user["email"] : ""), image: image.resource("icon_user_50x50.png"), action: :open_profile
load_async
end
def table_data
[{
cells: #matches.map do |match|
{
title: match[:attributes][:player2][:email],
subtitle: match[:attributes][:status],
action: :play_round,
arguments: { match: match }
}
end
}]
end
EDIT:
I have kept trying to solve this and I have now added a style to my UITableViewWrapperView object like this:
def viewDidLoad
super
rmq(UITableViewWrapperView).apply_style(:style_for_table_wrapper)
end
In my stylesheet I am able to therefore style everything: background_color, hidden status, but the frame style is just ignored.
def top_home_view(st)
st.frame = {l:20, t: 20, w: 300, h: 60}
st.background_color = color.white
end
As indicated in this Github issue:
https://github.com/infinitered/ProMotion/issues/784#issuecomment-230962988
the solution here lies in implementing a Header view for the TableScreen. This lets us have an area on top of the cells for our own use:
Define a table_header_view returning an instance of a UIView (required):
class HomeScreen < PM::TableScreen
# ...
def table_header_view
create!(TopHomeView, :top_home_view)
end
Note that the "bang method" (create!) will return an instance of UIView.
Credit goes to https://github.com/andrewhavens for clearing this up
I have a settings screen that works quite nicely using the "ProMotion-formotion" gem. I would like to make a couple of the rows into buttons that will call a method when pressed eg:
def table_data
set_nav_bar_button :left, title: "Cancel", action: :close
set_nav_bar_button :right, title: "Save", action: :submit
{sections:[{
title: 'Help',
rows: [{
title: "About",
type: :string,
editable: false,
action: :help #this is the sort of thing I want
}]
}, {
title: 'General',
rows: [
[...etc...]
Anyone know how I can achieve this?
edit: I've found a possible solution here:
How to use .on_delete callback in ProMotion-Formotion
But still wondering if there is a way of doing it within the table_data method.
Figured it out...
{
title: "Any Button",
type: :button,
key: :some_button
}
# later...
form.row(:some_button).on_tap do |row|
# do something when tapped
end
from here:
https://github.com/clayallsopp/formotion/blob/master/LIST_OF_ROW_TYPES.md#button
I am building a calendar application which requires certain events to display on the calendar based on the location that is being viewed. I have full calendar working in which it displays ALL the events in the database. I am trying to achieve an auto filter to only show the events that pertain to the location being viewed.
Current Setup (My Events Model is called "Campaigns" to align with my application)
Campaign Controller
def index
#campaigns = Campaign.all
#campaigns = #campaigns.after(params['start']) if (params['start'])
#campaigns = #campaigns.before(params['end']) if (params['end'])
respond_to do |format|
format.html # index.html.erb
format.json { render json: #campaigns }
end
end
Campaign Model
belongs_to :location
scope :before, lambda {|end_time| {:conditions => ["ends_at < ?", Campaign.format_date(end_time)] }}
scope :after, lambda {|start_time| {:conditions => ["starts_at > ?", Campaign.format_date(start_time)] }}
# need to override the json view to return what full_calendar is expecting.
# http://arshaw.com/fullcalendar/docs/event_data/Event_Object/
def as_json(options = {})
{
:id => self.id,
:title => self.name,
:description => "",
:start => starts_at.rfc822,
:end => ends_at.rfc822,
:allDay => false,
:recurring => false,
:url => Rails.application.routes.url_helpers.campaign_path(friendly_id)
}
end
def self.format_date(date_time)
Time.at(date_time.to_i).to_formatted_s(:db)
end
Script inside "Location" show.html.erb
$(document).ready(function() {
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
$('#calendar').fullCalendar({
editable: true,
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
defaultView: 'month',
loading: function(bool){
if (bool)
$('#loading').show();
else
$('#loading').hide();
},
// a future calendar might have many sources.
eventSources: [{
url: '/campaigns',
data: { <%= #locations %> }, #added but not filtering as I had hoped
color: 'blue',
textColor: 'white',
ignoreTimezone: false
}],
timeFormat: 'h:mm t{ - h:mm t} ',
dragOpacity: "0.5",
});
});
Currently I am able to achieve in displaying the campaigns that belong to the given location on the display side in the location show with:
<strong>Campaigns:</strong>
<%= render partial: #campaigns %>
</p>
And then in the location controller
def show
#campaigns = #location.campaigns
end
I have tried for hours to figure this out with no luck in getting the same result to the calendar. Can someone please help me in figuring out what is required to filter the "Campaigns" that pertain to the viewing location??
Thanks!
Have you tried this ?
eventSources: [{
url: '/campaigns',
data: { 'location': <%= #locations %> }, <- try this like so
color: 'blue',
textColor: 'white',
ignoreTimezone: false
}],
I've been trying to create an object to use in a jtable as the options (for a select list).
I don't seem to have the format correct. The jtable.org website says it will take an array:
From the jtable.org website:
http://jtable.org/ApiReference#fopt-options
PhoneType: {
title: 'Phone type',
options: [{ Value: '1', DisplayText: 'Home phone' }, { Value: '2', DisplayText: 'Office phone' }, { Value: '2', DisplayText: 'Cell phone' }]
}
However, when I create an object like that:
var optionsObject = [];
optionsObject.push({Value: i, DisplayText: 'Hello' + i});
and then use it as a variable for the options in my jtable:
key: true,
options: optionsObject,
I don't get the items in the select list drop down. I do get something in the select list, but that looks like '[object Object]' instead of the actual items.
I'm not really sure what I'm doing wrong.
If I send an object that looks like this:
object.push('hello' + i);
I will get an item in the select list that looks like this 'hello0', as expected, but then the display text is also used as the value. I need to have an object with separate display texts and values.
Has anybody had any success with doing this?
After much trial and error, and debugger stops in the jtable scripting files, I learned that in order to use an object for the 'options' property of a field in jtable, the object must be in the following format
var optionsObject = new Object();
optionsObject[Value] = DisplayText;
Is there any way to apply a template to the selected value of a ComboBox? I'm using a template to display the drop down values of the ComboBox, but as soon as i select one, the plain value from the datastore is shown.
{
id: 'requestStatusCombo',
hiddenName: 'requestStatus',
tpl: '<tpl for="."><div class="x-combo-list-item">{statusCode:requestStatus}</div></tpl>',
fieldLabel: 'Status',
xtype: 'combo',
mode: 'local',
triggerAction: 'all',
store: new Ext.data.ArrayStore({
fields: ['statusCode'],
data: [['unassigned'],['assigned'],['closed']]
}),
valueField: 'statusCode',
displayField: 'statusCode'
}
I want to use my format function requestStatus to translate the statusCodes into locale spesific status names, and this works well for the drop down list, but as soon as I select something, the statusCode is shown.
So is it possible to assign a template to the displayField, or perhaps do some simple batch modification on the datastore? By processing the input through a reader maybe? Is there another <tpl for="?"> keyword that will make this happen?
I'm looking for some simple method utilizing the Ext library. If the only solution is to pre process the data, I'm capable of doing that myself.
I found a solution!
I changed my datastore, and added a reader to pre-process the status using a convert function:
{
id: 'requestStatusCombo',
hiddenName: 'requestStatus',
fieldLabel: 'Status',
xtype: 'combo',
mode: 'local',
triggerAction: 'all',
store: new Ext.data.Store({
data: [['unassigned'],['assigned'],['closed']],
reader: new Ext.data.ArrayReader({},[
{name: 'statusCode', mapping: 0},
{name: 'displayname', mapping: 0, convert: function(statusCode) {
return Ext.util.Format.requestStatus(statusCode);
}}
])
}),
valueField: 'statusCode',
displayField: 'displayname'
}
Examinig generated DOM you will notice that while list elements are DIVs, the field itself is html INPUT element. You can't have HTML within INPUT element... so no... no xtemplate here.
This does not mean it can't be done by extending Ext.form.ComboBox (or Ext.Component maybe)