<?php

/**
 * @package elemental
 */
class ElementPublishChildren extends DataExtension {

	public function onBeforeVersionedPublish() {
		$staged = array();

		foreach($this->owner->Elements() as $widget) {
			$staged[] = $widget->ID;

			$widget->publish('Stage', 'Live');
		}

		// remove any elements that are on live but not in draft.
		$widgets = Versioned::get_by_stage('BaseElement', 'Live', "ParentID = '". $this->owner->ID ."' OR ListID = '".$this->owner->ID."'");

		foreach($widgets as $widget) {
			if(!in_array($widget->ID, $staged)) {
				$widget->deleteFromStage('Live');
			}
		}
	}
}
<?php

/**
 * @package elemental
 */
class ElementPublishChildren extends DataExtension {

	public function onBeforeVersionedPublish() {
		$staged = array();

		foreach($this->owner->Elements() as $widget) {
			$staged[] = $widget->ID;

			$widget->publish('Stage', 'Live');
		}

		// remove any elements that are on live but not in draft.
		$widgets = Versioned::get_by_stage('BaseElement', 'Live', "ParentID = '". $this->owner->ID ."'");

		foreach($widgets as $widget) {
			if(!in_array($widget->ID, $staged)) {
				$widget->deleteFromStage('Live');
			}
		}
	}
}
--- 
+++ 
@@ -15,7 +15,7 @@
 		}
 
 		// remove any elements that are on live but not in draft.
-		$widgets = Versioned::get_by_stage('BaseElement', 'Live', "ParentID = '". $this->owner->ID ."'");
+		$widgets = Versioned::get_by_stage('BaseElement', 'Live', "ParentID = '". $this->owner->ID ."' OR ListID = '".$this->owner->ID."'");
 
 		foreach($widgets as $widget) {
 			if(!in_array($widget->ID, $staged)) {
Add "OR ListID" check for element to element link

This is when elements are related to eachother and don't have a parent ID
