[gen] Added field.persist to avoid storing values for fields that do not require it (like master fields only used to determine selectable values among slave fields).

This commit is contained in:
Gaetan Delannay 2014-03-04 15:03:37 +01:00
parent b8ceb66a49
commit ea08d7981f
19 changed files with 106 additions and 75 deletions

View file

@ -417,7 +417,7 @@ class BaseMixin:
# Trigger field-specific validation
self.intraFieldValidation(errors, values)
if errors.__dict__:
rq.set('errors', errors.__dict__)
for k,v in errors.__dict__.iteritems(): rq.set('%s_error' % k, v)
self.say(errorMessage)
return self.gotoEdit()
@ -425,7 +425,7 @@ class BaseMixin:
msg = self.interFieldValidation(errors, values)
if not msg: msg = errorMessage
if errors.__dict__:
rq.set('errors', errors.__dict__)
for k,v in errors.__dict__.iteritems(): rq.set('%s_error' % k, v)
self.say(msg)
return self.gotoEdit()
@ -814,19 +814,27 @@ class BaseMixin:
res.append(field)
return res
def getSlaveFieldsRequestValues(self, pageName):
'''Returns the list of slave fields having a masterValue being a
method.'''
res = {}
def getSlavesRequestInfo(self, pageName):
'''When slave fields must be updated via Ajax requests, we must carry
some information from the global request object to the ajax requests:
- the selected values in slave fields;
- validation errors.'''
requestValues = {}
errors = {}
req = self.REQUEST
for field in self.getAllAppyTypes():
if field.page.name != pageName: continue
if field.masterValue and callable(field.masterValue):
# We have such a field
# We have a slave field that is updated via ajax requests.
name = field.name
# Remember the request value for this field if present.
if req.has_key(name) and req[name]:
res[name] = req[name]
return sutils.getStringDict(res)
requestValues[name] = req[name]
# Remember the validation error for this field if present.
errorKey = '%s_error' % name
if req.has_key(errorKey):
errors[name] = req[errorKey]
return sutils.getStringDict(requestValues), sutils.getStringDict(errors)
def getCssJs(self, fields, layoutType, res):
'''Gets, in p_res ~{'css':[s_css], 'js':[s_js]}~ the lists of

View file

@ -83,6 +83,20 @@ function evalInnerScripts(xhrObject, hookElem) {
for (var i=0; i<scripts.length; i++) { eval(scripts[i].innerHTML) }
}
function injectChunk(elem, content){
if (!isIe) elem.innerHTML = content;
else {
if (elem.tagName != 'TABLE') elem.innerHTML = content;
else {
/* IE doesn't want to replace content of a table. Force it to do so via
a temporary DOM element. */
var temp = document.createElement('div');
temp.innerHTML = content;
elem.replaceChild(temp.firstChild, elem.firstChild);
}
}
}
function getAjaxChunk(pos) {
// This function is the callback called by the AJAX machinery (see function
// askAjaxChunk below) when an Ajax response is available.
@ -93,13 +107,14 @@ function getAjaxChunk(pos) {
if (xhrObjects[pos].xhr.readyState == 1) {
// The request has been initialized: display the waiting radar
var hookElem = document.getElementById(hook);
if (hookElem) hookElem.innerHTML = "<div align=\"center\"><img src=\"ui/waiting.gif\"/><\/div>";
if (hookElem)
injectChunk(hookElem, "<div align=\"center\"><img src=\"ui/waiting.gif\"/><\/div>");
}
if (xhrObjects[pos].xhr.readyState == 4) {
// We have received the HTML chunk
var hookElem = document.getElementById(hook);
if (hookElem && (xhrObjects[pos].xhr.status == 200)) {
hookElem.innerHTML = xhrObjects[pos].xhr.responseText;
injectChunk(hookElem, xhrObjects[pos].xhr.responseText);
// Call a custom Javascript function if required
if (xhrObjects[pos].onGet) {
xhrObjects[pos].onGet(xhrObjects[pos], hookElem);
@ -229,12 +244,13 @@ function askComputedField(hookId, objectUrl, fieldName) {
}
function askField(hookId, objectUrl, layoutType, showChanges, masterValues,
requestValue){
requestValue, error){
// Sends an Ajax request for getting the content of any field.
var fieldName = hookId.split('_')[1];
var params = {'layoutType': layoutType, 'showChanges': showChanges};
if (masterValues) params['masterValues'] = masterValues.join('*');
if (requestValue) params[fieldName] = requestValue;
if (error) params[fieldName + '_error'] = error;
askAjaxChunk(hookId, 'GET', objectUrl, fieldName+':pxRender', params, null,
evalInnerScripts);
}
@ -354,7 +370,7 @@ function getSlaves(master) {
return res;
}
function updateSlaves(master, slave, objectUrl, layoutType, requestValues){
function updateSlaves(master,slave,objectUrl,layoutType,requestValues,errors){
/* Given the value(s) in a master field, we must update slave's visibility or
value(s). If p_slave is given, it updates only this slave. Else, it updates
all slaves of p_master. */
@ -382,15 +398,19 @@ function updateSlaves(master, slave, objectUrl, layoutType, requestValues){
var reqValue = null;
if (requestValues && (slaveName in requestValues))
reqValue = requestValues[slaveName];
askField(slaveId, objectUrl, layoutType, false, masterValues, reqValue);
var err = null;
if (errors && (slaveName in errors))
err = errors[slaveName];
askField(slaveId,objectUrl,layoutType,false,masterValues,reqValue,err);
}
}
}
function initSlaves(objectUrl, layoutType, requestValues) {
function initSlaves(objectUrl, layoutType, requestValues, errors) {
/* When the current page is loaded, we must set the correct state for all
slave fields. p_requestValues are those from the slave fields that must
be ajax-updated. */
slave fields. For those that are updated via Ajax requests, their
p_requestValues and validation p_errors must be carried to those
requests. */
slaves = getElementsHavingName('table', 'slave');
i = slaves.length -1;
while (i >= 0) {
@ -398,8 +418,7 @@ function initSlaves(objectUrl, layoutType, requestValues) {
master = document.getElementById(masterName);
// If master is not here, we can't hide its slaves when appropriate.
if (master) {
updateSlaves(master, slaves[i], objectUrl, layoutType, requestValues);
}
updateSlaves(master,slaves[i],objectUrl,layoutType,requestValues,errors);}
i -= 1;
}
}

View file

@ -141,9 +141,10 @@ class ToolWrapper(AbstractWrapper):
</x>''')
pxPageBottom = Px('''
<script type="text/javascript">:'initSlaves(%s,%s,%s)' % \
(q(zobj.absolute_url()), q(layoutType), \
zobj.getSlaveFieldsRequestValues(page))</script>''')
<script var="info=zobj.getSlavesRequestInfo(page)"
type="text/javascript">:'initSlaves(%s,%s,%s,%s)' % \
(q(zobj.absolute_url()), q(layoutType), info[0], info[1])
</script>''')
pxPortlet = Px('''
<x var="toolUrl=tool.url;

View file

@ -533,7 +533,7 @@ class AbstractWrapper(object):
pxEdit = Px('''
<x var="x=zobj.allows('write', raiseError=True);
errors=req.get('errors', None) or {};
errors=req.get('errors', {});
layout=zobj.getPageLayout(layoutType);
cssJs={};
phaseObj=zobj.getAppyPhases(currentOnly=True, \