N-N 双向关系未在 Jspresso 的用户界面上处理
N-N bidirectional relationships not handled on user interface with Jspresso
我正在研究 Jspresso 框架(使用 Swing 启动项目)。我在组件之间做了N-N个双向关系,但是没有出现这些关系对应的字段。
比如我有一个项目和学生的关系(一个学生可以有很多项目,一个项目可以有很多学生)。当我添加一个项目并在其详细视图中打开它时,我可以创建一个新学生并将其添加到项目中但我不能将现有学生添加到项目中,也不能在搜索视图中根据其学生搜索项目。
有没有办法显示这个?
这是我的view.groovy
// Implement your views here using the SJS DSL.
form('Project.pane',
parent:'decoratedView',
labelsPosition:'ASIDE',
columnCount:2,
fields: ['name','students','technologies','usesTrainers','technicalTrainers']){
actionMap{
actionList('FILE'){
action(ref:'saveModuleObjectFrontAction')
action(ref:'reloadModuleObjectFrontAction')
}
}
}
table'Project-students.table',
parent:'decoratedView',
actionMap:'masterDetailActionMap'
split_vertical'Project.proj.view',
model:'Project',
top:'Project.pane',
bottom:'Project-students.table'
form('Student.pane',
parent:'decoratedView',
labelsPosition:'ASIDE',
columnCount:2){
actionMap{
actionList('FILE'){
action(ref:'saveModuleObjectFrontAction')
action(ref:'reloadModuleObjectFrontAction')
}
}
}
table'Student-technologies.table',
parent:'decoratedView',
actionMap:'masterDetailActionMap'
split_vertical'Student.proj.view',
model:'Student',
top:'Student.pane',
bottom:'Student-technologies.table'
form('Trainer.pane',
parent:'decoratedView',
labelsPosition:'ASIDE',
columnCount:5)
form('Technology.pane',
parent:'decoratedView',
labelsPosition:'ASIDE',
columnCount:5)
这是我的 model.groovy
// Implement your domain here using the SJS DSL.
Interface('Traceable',
interceptors: 'TraceableLifecycleInterceptor',
uncloned: ['createTimestamp',
'lastUpdateTimestamp','lastUpdatedBy','createdBy']) {
string_64 'createdBy',readOnly:true
date_time 'createTimestamp', timeZoneAware: true, readOnly: true
string_64 'lastUpdatedBy', readOnly:true
date_time 'lastUpdateTimestamp', timeZoneAware: true, readOnly: true
}
Entity ('Project', extend:'Traceable',toString:'name',
icon:'project.png',
rendered: ['name','lastUpdateTimestamp','lastUpdatedBy','createTimestamp','createdBy'],
queryable: ['name']){
string_64 'name'
set 'technologies', composition:true, ref:'Technology'
set 'technicalTrainers', composition:true, ref:'Trainer'
set 'usesTrainers', composition:true, ref:'Trainer'
set 'students', composition:true, ref:'Student'
}
Entity ('Technology', extend:'Traceable',toString:'name',
icon:'technology.png',
rendered: ['name','lastUpdateTimestamp','lastUpdatedBy','createTimestamp','createdBy'],
queryable: ['name']){
string_64 'name'
set 'projects', ref:'Project', reverse:'Project-technologies'
set 'studentsAbleToUseIt', ref:'Technology', reverse:'Student-technologies'
set 'trainersAbleToTeachIt', ref:'Technology', reverse:'Trainer-technologies'
}
Interface ('Person', extend:'Traceable'){
string_64 'lastname'
string_64 'firstname'
date_time 'createTimestamp', timeZoneAware: true, readOnly: true
date_time 'lastUpdateTimestamp', timeZoneAware: true, readOnly: true
}
Entity ('Trainer',
extend: 'Person',
toString:'firstname',
icon:'trainer.png',
rendered: ['firstname','lastname','lastUpdateTimestamp','lastUpdatedBy','createTimestamp','createdBy'],
queryable: ['firstname','lastname']){
set 'projectsAsTechnicalTrainer', ref:'Project', reverse:'Project-technicalTrainers'
set 'projectsAsUsesTrainer', ref:'Project', reverse:'Project-usesTrainers'
set 'technologies', composition:true, ref:'Technology'
date_time 'createTimestamp', timeZoneAware: true, readOnly: true
date_time 'lastUpdateTimestamp', timeZoneAware: true, readOnly: true
}
Entity ('Student',
extend: 'Person',
toString:'firstname',
icon:'student.png',
rendered: ['firstname','lastname','lastUpdateTimestamp','lastUpdatedBy','createTimestamp','createdBy'],
queryable: ['firstname','lastname']){
set 'technologies', composition:true, ref:'Technology'
set 'projects', ref:'Project', reverse:'Project-students'
date_time 'createTimestamp', timeZoneAware: true, readOnly: true
date_time 'lastUpdateTimestamp', timeZoneAware: true, readOnly: true
}
你绝对可以轻松实现这两个目标。
1/一个N-N
关系可以简单的看成两个1-N
关系。因此,您可以在面向 Project
的视图上使用 Project-students
关系,在面向学生的视图上使用 Student-projects
关系。您可以使用 2 个不同的过滤器模块(一个在 Project
上,一个在 Student
上)或补充您的 Project.proj.view
,以便通过添加额外的 table 将在第一个 table 详细信息中显示 selected 学生的 Student-projects
。
类似于:
split_vertical ('Project.proj.view',
model:'Project',
top:'Project.pane') {
bottom {
split_horizontal(
left: 'Project-students.table',
right: 'Student-projects.table',
cascadingModels: true
)
}
}
2/ 关于 select 并将现有 Project
或 Student
添加到相应集合的能力,您可以使用自定义 LOV 操作,如 1st chapter of the Jspresso-CE reference documentation.
类似于:
table('Project-students.table') {
actionMap {
actionList('EDIT'){
action(parent:'lovAction',
custom:[
autoquery:false,
entityDescriptor_ref:'Student',
okAction_ref:'addAnyToMasterFrontAction'
]
)
action(ref:'removeAnyCollectionFromMasterFrontAction')
}
}
}
3/ 至于通过Student
(或相反)过滤Project
,Jspresso 支持将集合属性定义为过滤器属性。在这种情况下,筛选视图将为学生安装一个 LOV,以筛选项目。
如果您想在每个项目过滤器视图上默认使用它,请直接在模型上声明它。
类似于:
Entity ('Project'
...
queryable : ['name', 'students']
...){
...
}
我正在研究 Jspresso 框架(使用 Swing 启动项目)。我在组件之间做了N-N个双向关系,但是没有出现这些关系对应的字段。 比如我有一个项目和学生的关系(一个学生可以有很多项目,一个项目可以有很多学生)。当我添加一个项目并在其详细视图中打开它时,我可以创建一个新学生并将其添加到项目中但我不能将现有学生添加到项目中,也不能在搜索视图中根据其学生搜索项目。 有没有办法显示这个?
这是我的view.groovy
// Implement your views here using the SJS DSL.
form('Project.pane',
parent:'decoratedView',
labelsPosition:'ASIDE',
columnCount:2,
fields: ['name','students','technologies','usesTrainers','technicalTrainers']){
actionMap{
actionList('FILE'){
action(ref:'saveModuleObjectFrontAction')
action(ref:'reloadModuleObjectFrontAction')
}
}
}
table'Project-students.table',
parent:'decoratedView',
actionMap:'masterDetailActionMap'
split_vertical'Project.proj.view',
model:'Project',
top:'Project.pane',
bottom:'Project-students.table'
form('Student.pane',
parent:'decoratedView',
labelsPosition:'ASIDE',
columnCount:2){
actionMap{
actionList('FILE'){
action(ref:'saveModuleObjectFrontAction')
action(ref:'reloadModuleObjectFrontAction')
}
}
}
table'Student-technologies.table',
parent:'decoratedView',
actionMap:'masterDetailActionMap'
split_vertical'Student.proj.view',
model:'Student',
top:'Student.pane',
bottom:'Student-technologies.table'
form('Trainer.pane',
parent:'decoratedView',
labelsPosition:'ASIDE',
columnCount:5)
form('Technology.pane',
parent:'decoratedView',
labelsPosition:'ASIDE',
columnCount:5)
这是我的 model.groovy
// Implement your domain here using the SJS DSL.
Interface('Traceable',
interceptors: 'TraceableLifecycleInterceptor',
uncloned: ['createTimestamp',
'lastUpdateTimestamp','lastUpdatedBy','createdBy']) {
string_64 'createdBy',readOnly:true
date_time 'createTimestamp', timeZoneAware: true, readOnly: true
string_64 'lastUpdatedBy', readOnly:true
date_time 'lastUpdateTimestamp', timeZoneAware: true, readOnly: true
}
Entity ('Project', extend:'Traceable',toString:'name',
icon:'project.png',
rendered: ['name','lastUpdateTimestamp','lastUpdatedBy','createTimestamp','createdBy'],
queryable: ['name']){
string_64 'name'
set 'technologies', composition:true, ref:'Technology'
set 'technicalTrainers', composition:true, ref:'Trainer'
set 'usesTrainers', composition:true, ref:'Trainer'
set 'students', composition:true, ref:'Student'
}
Entity ('Technology', extend:'Traceable',toString:'name',
icon:'technology.png',
rendered: ['name','lastUpdateTimestamp','lastUpdatedBy','createTimestamp','createdBy'],
queryable: ['name']){
string_64 'name'
set 'projects', ref:'Project', reverse:'Project-technologies'
set 'studentsAbleToUseIt', ref:'Technology', reverse:'Student-technologies'
set 'trainersAbleToTeachIt', ref:'Technology', reverse:'Trainer-technologies'
}
Interface ('Person', extend:'Traceable'){
string_64 'lastname'
string_64 'firstname'
date_time 'createTimestamp', timeZoneAware: true, readOnly: true
date_time 'lastUpdateTimestamp', timeZoneAware: true, readOnly: true
}
Entity ('Trainer',
extend: 'Person',
toString:'firstname',
icon:'trainer.png',
rendered: ['firstname','lastname','lastUpdateTimestamp','lastUpdatedBy','createTimestamp','createdBy'],
queryable: ['firstname','lastname']){
set 'projectsAsTechnicalTrainer', ref:'Project', reverse:'Project-technicalTrainers'
set 'projectsAsUsesTrainer', ref:'Project', reverse:'Project-usesTrainers'
set 'technologies', composition:true, ref:'Technology'
date_time 'createTimestamp', timeZoneAware: true, readOnly: true
date_time 'lastUpdateTimestamp', timeZoneAware: true, readOnly: true
}
Entity ('Student',
extend: 'Person',
toString:'firstname',
icon:'student.png',
rendered: ['firstname','lastname','lastUpdateTimestamp','lastUpdatedBy','createTimestamp','createdBy'],
queryable: ['firstname','lastname']){
set 'technologies', composition:true, ref:'Technology'
set 'projects', ref:'Project', reverse:'Project-students'
date_time 'createTimestamp', timeZoneAware: true, readOnly: true
date_time 'lastUpdateTimestamp', timeZoneAware: true, readOnly: true
}
你绝对可以轻松实现这两个目标。
1/一个N-N
关系可以简单的看成两个1-N
关系。因此,您可以在面向 Project
的视图上使用 Project-students
关系,在面向学生的视图上使用 Student-projects
关系。您可以使用 2 个不同的过滤器模块(一个在 Project
上,一个在 Student
上)或补充您的 Project.proj.view
,以便通过添加额外的 table 将在第一个 table 详细信息中显示 selected 学生的 Student-projects
。
类似于:
split_vertical ('Project.proj.view',
model:'Project',
top:'Project.pane') {
bottom {
split_horizontal(
left: 'Project-students.table',
right: 'Student-projects.table',
cascadingModels: true
)
}
}
2/ 关于 select 并将现有 Project
或 Student
添加到相应集合的能力,您可以使用自定义 LOV 操作,如 1st chapter of the Jspresso-CE reference documentation.
类似于:
table('Project-students.table') {
actionMap {
actionList('EDIT'){
action(parent:'lovAction',
custom:[
autoquery:false,
entityDescriptor_ref:'Student',
okAction_ref:'addAnyToMasterFrontAction'
]
)
action(ref:'removeAnyCollectionFromMasterFrontAction')
}
}
}
3/ 至于通过Student
(或相反)过滤Project
,Jspresso 支持将集合属性定义为过滤器属性。在这种情况下,筛选视图将为学生安装一个 LOV,以筛选项目。
如果您想在每个项目过滤器视图上默认使用它,请直接在模型上声明它。
类似于:
Entity ('Project'
...
queryable : ['name', 'students']
...){
...
}