How do we create a pre-defined Asset upload field in a plugin that integrates with the native Craft Assets file manager? We've got a plugin.  It doesn't have the ability to add custom field types.  We're pre-defining all of the fields.  One of the fields needs to be an Asset field.  A user should be able to upload an Asset using the native Craft Asset UI, store that Asset locally or on Amazon or any supported cloud platforms.

How do we do this?

Where do we create the relationship between the uploaded Asset and the database record we want the Asset related to?

If we were allowing custom fields we could have our custom table relate to a Field Layout ID, and have any number of fields relate to that Field Layout.  But in our case, we're defining all of the columns we need in our template, in our own record, and don't really need to create any fields within Craft's fields table as we're setting them all up beforehand.

Do we need a Field Layout in this situation?  Do we need to create a Field within Craft under our own context (like Matrix blocks) to be able to control the settings such as where to upload the assets to, and whether to restrict the upload to a single folder, or single image?

I feel I have lots of pieces of the puzzle, but can't yet see how they fit together.
I did this recently with my Ad Wizard plugin... There are several different parts which need to be brought together to make it work:



In your Record file, add this to defineRelations:

'asset' =&gt; array(static::BELONGS_TO, 'AssetFileRecord')




In your Model file, add this to defineAttributes:

'assetId' =&gt; AttributeType::Number




Whichever template is responsible for editing that data will need something like this:

&lt;div class="field" id="assetId-field"&gt;
    &lt;div class="heading"&gt;
        &lt;label for="assetId"&gt;Image&lt;/label&gt;
    &lt;/div&gt;
    &lt;div class="input"&gt;
        {% if assetsSourceExists %}
            {{ forms.elementSelect({
                elements: elements,
                id: 'assetId',
                name: 'assetId',
                elementType: elementType,
                criteria: {"kind":[],"localeEnabled":null,"locale":"en_us"},
                sourceElementId: assetId,
                jsClass: 'Craft.AssetSelectInput',
                addButtonLabel: 'Select Image',
                limit: 1,
            }) }}
        {% else %}
            &lt;p class="error"&gt;No assets sources currently exist. &lt;a href="{{ newAssetsSourceUrl }}"&gt;Create one now...&lt;/a&gt;&lt;/p&gt;
        {% endif %}
    &lt;/div&gt;
&lt;/div&gt;


You'll notice in the Twig code above, I set references to the following variables:


assetId
elements
elementType
assetsSourceExists
newAssetsSourceUrl


These variable were set in the actionEditMyElement method of the Controller prior to loading the template:

// Set assetId
$variables['assetId'] = $myModel-&gt;assetId;

// Set elements
if ($variables['assetId']) {
    $asset = craft()-&gt;elements-&gt;getElementById($variables['assetId']);
    $variables['elements'] = array($asset);
} else {
    $variables['elements'] = array();
}

// Set elementType
$variables['elementType'] = craft()-&gt;elements-&gt;getElementType(ElementType::Asset);

// Set assetsSourceExists
$sources = craft()-&gt;assets-&gt;findFolders();
$variables['assetsSourceExists'] = count($sources);

// Set newAssetsSourceUrl
$variables['newAssetsSourceUrl'] = UrlHelper::getUrl('settings/assets/sources/new');

// Render the template!
$this-&gt;renderTemplate('myplugin/_edit', $variables);




Your Controller will probably have something like this in your actionSaveMyElement method:

$myModel-&gt;assetId = craft()-&gt;request-&gt;getPost('assetId', $myModel-&gt;assetId);




Your Service file will probably have something like this to save your record:

$assetId = (!empty($myModel-&gt;assetId) ? $myModel-&gt;assetId[0] : null);
$myRecord-&gt;assetId = $assetId;
...
$myRecord-&gt;save();




Hope that helps, let me know if I missed anything!