LOADのパラメータを可変にする使い方について質問

72 views
Skip to first unread message

Mitsuhiro Tsuda

unread,
May 9, 2013, 10:20:44 AM5/9/13
to web2py...@googlegroups.com
津田です。

LOADのパラメータを可変にする使い方についてお教えください。

ページ内で、データ・テーブルの編集にモーダルウィンドウ(風の表現)を使いたいのですが、LOADにページ内部からパラメータを渡す方法が分かりません。
下記は簡単な(web2pyのbookから寄せ集めの)コードですが、indexページの内部で、#click1で、新規の登録動作はします。
#click1をクリックするとダイアログDIVが中央に表示され、SQLFORMが表示されます。登録すると、DIVは閉じget_listで一覧を表示します。
LOADのargsを変更するために、/myapp/test/index/2 などとすると、対象が編集できますが、index/2
ではなく内部のリンク(実際にはデータ一覧のid)で同様のことをしたいのです。ここでは#click2で代用しています。

他の方法で行うことはできると思いますが、LOADやajaxという便利な機能があるので・・・しかし、試しているうちに分からなくなってしまいました。
複雑に考え過ぎなのでしょうか?

よろしくお願いします。

==========

model: db.py
#データテーブルは適当です。下記は特に意味はありません。

db.define_table('thing',
Field('name',requires=IS_NOT_EMPTY())
)
---

controller: /myapp/test/index.py

def index():
return dict()

def get_list():
rows=db(db.thing.id>0).select()
return dict(list=rows)

def manage_things():
record = None
if len(request.args)>0: record = db.thing(request.args(0,cast=int))
form = SQLFORM(db.thing, record, deletable=True)
if form.process().accepted:
response.flash = 'form accepted'
response.js = 'close_modal()'
elif form.errors:
response.flash = 'form has errors'
return dict(form=form)

----

view: test/index.html

{{extend 'layout.html'}}

<a id="click1">[new]</a>
<a id="click2">[update]</a>

<div id="list"></div><!-- 一覧表示用 -->

<div id="cover"></div><!-- モーダル用背景カバー -->

<!-- 編集用DIV、request.args は仮、ここを操作したい -->
<div id="air">{{=LOAD("test","manage_things.load",args=request.args,
ajax=True)}}</div>

<script>
var open_modal = function(){
jQuery('#cover,#air').show();
}
var close_modal = function(){
jQuery("#cover,#air").hide();
}

jQuery('#click1').bind('click', function() {
open_modal();
return false;
});
jQuery('#click2').bind('click', function() {
//
//ここにLOADのargs変数を操作する何らかの仕組み?を入れたい
//しかし、ここでなくても良い(手法はこだわらない)
//
open_modal();
return false;
});
jQuery('#cover').bind('click',function(){
// モーダル用背景カバーを閉じる
close_modal();
return false;
});
</script>

----

viewer: test/manage_things.load
<!-- LOADによって#airに表示、また、ajax機能でテーブルの内容を表示 -->

{{=form}}

<script>
ajax('{{=URL('get_list.load')}}', ['name'], 'list');
</script>

----

viewer: test/get_list.load
<!-- 単にインデックスindexにテーブルの一覧を表示するのみ -->

{{=list}}

----

static: css/test.css
/* 簡単なモーダル風ダイアログ(疑似) */

#main{
display: relative;
}
#cover{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: #000;
opacity: 0.3;
display: none;
cursor: pointer;
}
#air{
position: absolute;
left: 50%;
top: 20%;
width: 50%;
height: 50%;
margin-top: 0;
margin-left: -25%;
background-color: #fff;
padding: 25px;
display: none;
z-index: 1;
}
==========

kato

unread,
May 9, 2013, 1:26:29 PM5/9/13
to web2py...@googlegroups.com
津田さん

次のようにコードをセットしたらどうでしょうか?。

コントローラの /myapp/test/index.py の get_list


def get_list():
    rows=db(db.thing.id>0).select()
    return dict(list=rows)

を次のように変更


def get_list():
    db.thing.id.represent = lambda r :A(r, _href=URL(f='index', extension='html', args=r))
    rows = db(db.thing).select()
    return dict(list=rows)

これによって、things.id がリンクに変わり、該当IDの修正が可能になります。

KATO


2013年5月9日 11:20 Mitsuhiro Tsuda <mi.t...@gmail.com>:

--
このメールは Google グループのグループ「web2py japan」の登録者に送られています。
このグループから退会し、メールの受信を停止するには、web2py-japan...@googlegroups.com にメールを送信します。
その他のオプションについては、https://groups.google.com/groups/opt_out にアクセスしてください。



Mitsuhiro Tsuda

unread,
May 9, 2013, 9:09:52 PM5/9/13
to web2py...@googlegroups.com
KATOさん、アドバイスありがとうございます。

request.argsに値がセットされますので、確かに動作しますが、ページがテーブルのidリンクをクリックするたびに読み込まれてしまいます。
私の質問が紛らわしかったので、改めます。

view: test/index.html
の下記の箇所は、LOADをjQueryで動的に書き換えることができなかった(方法が悪いかもしれませんが)ので、パラメータを渡すには args
の方法かと思い書きました。

>> <!-- 編集用DIV、request.args は仮、ここを操作したい -->
>> <div id="air">{{=LOAD("test","manage_things.load",args=request.args,ajax=True)}}</div>

行いたいことは、
LOAD('test','manage_things.load',ajax=True)
のような記述に関して、indexのページ内で(argsでもvarsでも良いのですが、)LOADにJavaScriptから動的にパラメータを渡すことです。

idのリンクでスクリプトを呼び出して、jQueryの$ajaxで処理することもできるでしょうが、web2pyのLOADだけで処理できるのであれば、と考えます。




2013年5月10日 2:26 kato <hi21a...@yahoo.co.jp>:

kato

unread,
May 10, 2013, 6:43:54 AM5/10/13
to web2py...@googlegroups.com
LOADにJavaScriptから動的にパラメータを渡すことです。

一旦 LOAD の部分だけ消して、再度LOADを呼び直したらどうでしょうか?。
例えば次のように設定します。

コントローラの /myapp/test/index.py の get_list を次のように変更します。

def get_list():
    onclick_ajax = "jQuery.noConflict();\
                    jQuery('#load').remove();\
                    jQuery('#dummy_id').val(jQuery(this).text());\
                    ajax('_manage_things', ['dummy_id'], 'air');"
    db.thing.id.represent = lambda r :A(r, _onclick=onclick_ajax)
    rows = db(db.thing).select()
    return dict(list=rows)



画面上のLOAD部分を消して、ajax関数を呼びます。
コントローラの /myapp/test/index.py に _manage_things を追加します。

def _manage_things():
    return LOAD('index', 'manage_things.load', args=[request.vars.dummy_id], ajax=True, target='load')

test/index.html に dymmy_id 隠しフィールドを追加します。

<input type='hidden' name='dummy_id' id='dummy_id' value=''>
さらに、LOADにtargetパラメータを追加します。

<!-- 編集用DIV、request.args は仮、ここを操作したい -->
<div id='air'>{{=LOAD('index', 'manage_things.load', ajax=True, target='load')}}</div>

これで画面全体を書き換えずに、LOAD部分だけ変更できるようになると思います。

KATO


2013年5月9日 22:09 Mitsuhiro Tsuda <mi.t...@gmail.com>:

Mitsuhiro Tsuda

unread,
May 10, 2013, 9:26:22 PM5/10/13
to web2py...@googlegroups.com
LOADを書き換えるのはかなり力技と感じました。
そこで、改めてその方向を調べて、解決できました。

生成コードをみてLOADが行っているのは、
1.ajax_component() 関数に読み込むURLとtarget (DIVのid)に関連づけ、
2.リンク先のURLをtargetのDIVに読み込むこと
とみました。(LOADのパラメータでいろいろ変化しますね。)

Aヘルパーのcidの役割がやっとわかりましたので、これを使って、次のようにしました。
Aヘルパーはajax_component()をaタグにonclickで組み込むので、結局、LOADはこの目的では不要になってしまいました。
(LOADのajax属性がFalseでよくなってしまったため、実現にはLOADでなくても良いことになりました。下記ではコメント化してあります。)
manage_things.loadのリストを読み込むajaxはその目的だけのためにindex.htmlに移動しました。(これはすっきりします。)

=======

controller: test.py

def index():
return dict()

def get_list():

#ここをKATOさんのコードからヒントを得て変更、cidでターゲットを設定
db.thing.id.represent = lambda r :A(r,
_href=URL(f='manage_things', extension='load', args=r), cid='air')

rows = db(db.thing).select()
return dict(list=rows)

def manage_things():
record = None
if len(request.args)>0: record = db.thing(request.args(0,cast=int))
form = SQLFORM(db.thing, record, deletable=True)
if form.process().accepted:
response.flash = 'form accepted'

#モーダルをcloseし、一覧を更新
response.js = 'close_modal();update_list()'

elif form.errors:
response.flash = 'form has errors'
return dict(form=form)

----

view: test/index.html

// ここでargsを与えずに新規作成(このためLOADが不要になる)
{{=A('[new]', _id='new', _href=URL(f='manage_things',
extension='load'), cid='air')}}

<div id="list"></div>

<div id="cover"></div>
<div id="air">

// 不要になったLOADを一時コメント化
{{#=LOAD(f='manage_things', extension='load', target='target')}}

</div>

<script>
var open_modal = function(){
jQuery('#cover,#air').show();
}
var close_modal = function(){
jQuery("#cover,#air").hide();
}

// 仮に、一覧の更新はこういう方法で。
var update_list = function(){
ajax("{{=URL('get_list.load')}}", ['name'], "list");
}

jQuery('#new').bind('click', function() {
open_modal(); return false;
});
jQuery('#cover').bind('click',function(){
close_modal(); return false;
});

// ちょっと細工
jQuery(document).ready(function(){

// 一応chromeでは動いているが他では分からない・・・。
// jQueryのclickイベントとAのhref、onclickの関係は調べねば・・・
$("#list a").live("click",function(evt){
open_modal(); return false;
});

// 最初の表示
update_list();
});
</script>

-----

このような感じで行けるのかもしれません。結局ポイントはAヘルパーのcidでしたが、便利に使ってゆけそうです。
KATOさん、アドバイスをありがとうございました。

津田



2013年5月10日 19:43 kato <hi21a...@yahoo.co.jp>:
Reply all
Reply to author
Forward
0 new messages