TL;DR (Short synopsis):
I have recreated the admin “Add” button in my own project. However, when I hit “save” on the parent form, it is not recognizing the new select element.
Whole Story:
I have that functionality working in my own project… almost. I need help figuring out the last step. As it is now, I have a “+” button, I click it, a popup shows up, I add a new object, hit save, popup closes and that new item is now in my select box and selected – just like the admin page. However, when I hit save on this parent form, I get the error that I’ve selected an item not in the list. Of course, since the page has reloaded, my new item is part of the list and I just hit save again and it works. Of course, I need it to save on the first time!
The basic setup is my Parent model is called System and the foreign key model is called Zone. The Zone model lists how many zones a system has (1 zone,2 zones,10 zones, etc…)
OK, some code:
The “Add” link in the template of the parent form:
<a href="/systems/zones/new/?popup=1" id="add_id_numZones" onclick="return showAddPopup(this);">Add</a>
In my New_Zone view, after saving the new zone, I check if the popup GET variable is 1, if so, return a javascript function. Here’s the view:
...
if form.is_valid():
f = form.save(commit=False)
pk_value = f.numOfZones
form.save()
obj = Zone_Info.objects.get(numOfZones=pk_value)
if isPopup == "1":
return HttpResponse('<script>opener.closeAddPopup(window, "%s", "%s");</script>' % (escape(pk_value), escape(obj)))
...
And here is my Javascript (largely copied from the admin javascript:
function html_unescape(text) {
// Unescape a string that was escaped using django.utils.html.escape.
text = text.replace(/</g, '<');
text = text.replace(/>/g, '>');
text = text.replace(/"/g, '"');
text = text.replace(/'/g, "'");
text = text.replace(/&/g, '&');
return text;
}
function windowname_to_id(text) {
text = text.replace(/__dot__/g, '.');
text = text.replace(/__dash__/g, '-');
return text;
}
function showAddPopup(triggeringLink, pWin) {
var name = triggeringLink.id.replace(/^add_/, '');
href = triggeringLink.href;
var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
win.focus();
return false;
}
function closeAddPopup(win, newID, newRepr) {
newID = html_unescape(newID);
newRepr = html_unescape(newRepr);
var name = windowname_to_id(win.name);
var elem = document.getElementById(name);
if (elem) {
if (elem.nodeName == 'SELECT') {
var o = new Option(newRepr, newID);
elem.options[elem.options.length] = o;
o.selected = true;
} else if (elem.nodeName == 'INPUT') {
if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) {
elem.value += ',' + newID;
} else {
elem.value = newID;
}
}
} else {
var toId = name + "_to";
elem = document.getElementById(toId);
var o = new Option(newRepr, newID);
SelectBox.add_to_cache(toId, o);
SelectBox.redisplay(toId);
}
win.close();
}
I took a look at this question and it seems that I am doing precisely the same thing.
Any ideas on how to get that last step of getting the form to recognize the new select element?
Thanks!
I Figured it Out
The problem was what I was passing to my
closeAddPopupjavascript function. Essentially, I was passing garbage values.Here’s what I originally had in my
New_Zoneview (which didn’t work):It’s a pretty stupid mistake on my part (clearly it’s late). I was assigning
fto the fieldnumOfZoneswhich I thought was thepkand sending that to the script.Now, the working view looks like this:
Anyway… thanks to… well, Stackoverflow. I don’t think I would have solved the problem without posting the question and rereading my code on stackoverflow.