7912 Posts in 1355 Topics by 930 members
DataObjectManager Module
SilverStripe Forums » DataObjectManager Module » HOWTO: HasMany and ManyMany new items default to checked
Discuss the DataObjectManager module, and the related ImageGallery module.
Moderators: martimiz, UncleCheese, Howard, Sean, Ryan M., biapar, Willr, Ingo, swaiba, simon_w
|
Page:
1
|
Go to End | |
| Author | Topic: | 1540 Views |
-
HOWTO: HasMany and ManyMany new items default to checked

12 August 2010 at 10:30am Last edited: 6 October 2010 4:50pm
Edit: fixed recursion bug when trying to add an image into a set it already belongs to (eg. multiple DOM instances open at once in different browser windows)
Hi list
Quick tip for anyone who would like newly created items in a HasManyDataObjectManager or ManyManyDataObjectManager to default to belonging to the item you created them in.
HasManyDataObjectManager
In your child DataObject:
class ChildObject extends DataObject {
. . .
/**
* Add newly created items to the parent
*/
function onAfterWrite() {
$relatedClass = 'ParentClassname';
$referringField = 'ParentReferringField';
if ( array_key_exists('ctf[parentClass]', $this->record)
&& $this->record['ctf[parentClass]'] == $relatedClass ) {
$parentRecord = DataObject::get_by_id(
$relatedClass,
(int)$this->record['ctf[sourceID]']
);
$components = $parentRecord->getComponents($referringField);
if ( ! in_array($this->ID, $components->getIdList()) ) {
$components->add($this->ID);
$components->write();
}
}
parent::onAfterWrite();
}}
You only need change two lines, the $relatedClass and $referringField vars. $relatedClass is the parent classname, and $referringField is the fieldname on the parent that points to the child object in question.
ManyManyDataObjectManager
In the child object:
class ChildObject extends DataObject {
. . .
/**
* Add newly created items to the parent
*/
function onAfterWrite() {
$relatedField = 'RelatedFieldName';
$relatedClass = 'RelatedClassName';
if ( array_key_exists('ctf[parentClass]', $this->record)
&& $this->record['ctf[parentClass]'] == $relatedClass ) {
$components = $this->getManyManyComponents($relatedField);
if ( ! in_array((int)$this->record['ctf[sourceID]'], $components->getIdList()) ) {
$components->add((int)$this->record['ctf[sourceID]']);
$components->write();
}
}
parent::onAfterWrite();
}}
Again, only two lines need to be changed. The $relatedField is the fieldname on the child object that points to the parent in question, and the $relatedClass is the classname of the parent in question.
Javascript update
There is some code in dataobject_manager.js that retains the previous selection status of the items. It doesn't take into account newly created items though; here's a replacement refresh() function that does. It's on line 374 (depending on your version of course) of dataobject_manager.js.
function refresh($div, link, focus)
{
// Kind of a hack. Pass the list of ids to the next refresh
var listValue = ($div.hasClass('RelationDataObjectManager'))
? jQuery('#'+$div.attr('id')+'_CheckedList').val() : false;
// Make a list of all ids so we can detect newly created ones
var all = ',';
$div.find('li.data input:checkbox').each(function(i,el) {
all += el.value+',';
});
jQuery.ajax({
type: "GET",
url: link,
success: function(html){
if(!$div.next().length && !$div.prev().length)
$div.parent().html(html);
else
$div.replaceWith(html);
if(listValue)
jQuery('#'+$div.attr('id')+'_CheckedList').attr('value',listValue);
// Add newly created items in if checked
jQuery(html).find('li.data input:checkbox').each(function(i,el) {
el = jQuery(el);
if ( el.attr('checked') && jQuery.inArray(el.val(), all.split(',')) == -1 ) {
jQuery('#'+$div.attr('id')+'_CheckedList').val(
jQuery('#'+$div.attr('id')+'_CheckedList').val()+el.val()+','
);
}
});var $container = jQuery('#'+$div.attr('id'));
$container.DataObjectManager();
if (typeof focus == 'string') $container.find(focus).focus();
//jQuery('#'+$div.attr('id')).DataObjectManager();
}
});
}Hope this helps somebody!
-
Re: HOWTO: HasMany and ManyMany new items default to checked

12 August 2010 at 12:28pm
I posted this solution a while ago. You shouldn't need to update the javascript or anything.
This is what I do:
public function onAfterWrite()
{
parent::onAfterWrite();
if(isset($_REQUEST['ctf'])) {
// new record?
if(!isset($_REQUEST['ctf']['childID']))
DB::query("INSERT INTO `[YOUR_JOIN_TABLE]` SET [PARENT_TABLE_ID] = ". $_REQUEST['ctf']['sourceID'] . ", [CHILD_TABLE_ID] = $this->ID");
}
} -
Re: HOWTO: HasMany and ManyMany new items default to checked

17 August 2010 at 5:17pm
If you have a few items in your DOM already, and then add a new one, the new item's checkbox always gets unchecked by the JS, because it's not in the 'remembered' list. By default that's fine because new items are unchecked by default.
If you change the default behaviour to make new items checked by default, as above, your new item is now incorrectly unchecked by the stock JS. The above JS fix checks for new items on refresh, and leaves their checkbox state unchanged. Feel free to use it if you think it is an improvement.
Cheers
-
Re: HOWTO: HasMany and ManyMany new items default to checked

18 August 2010 at 1:13am
Oh, right. Yeah, I forgot about that hack. Cool, thanks for the heads up.
-
Re: HOWTO: HasMany and ManyMany new items default to checked

8 March 2012 at 11:20am
Hey gents--
I'm trying to do the opposite -- I have a Category DataObject which has a $belongs_many_many relationship to a NewsPage, which has the corresponding $many_many there. As a result I have the relation table NewsPage_Categories.
What I'd like to do is to automatically associate a given Category with a newly created page so that there is always at least one Category selected. Seems like it would just be a simple INSERT INTO in an OnAfterWrite() function but alas, no such luck. It's not happening for me. here's my very simple code (in the NewsPage class):
function onAfterWrite() {
parent::onAfterWrite();
if(isset($_REQUEST['ctf'])) {
DB::query("INSERT INTO `NewsPage_Categories` SET `NewsPageID` = '".$_REQUEST['ctf']['sourceID']."', `CategoryID` = '1'");
}
}What's wrong with this picture? I surmised from the code posted above that the $_REQUEST['ctf']['sourceID'] is the ID of the newly created Page. But I am not getting an error; it's just that the insert doesn't occur. onAfterWrite(), however, is firing.
Thanks in advance,
Garrett
| 1540 Views | ||
|
Page:
1
|
Go to Top |


