A few days ago I implemented a custom field which should have 2 dropdowns which are depending on each other (here you can find the whole implementation, in this example I will just show you a simple text field).
So I checked all possible solutions and I decided to use the IFrame
type for that. This is a default field provided by Sitecore. So in the source input on the template you need to provide the url for your iframe. In my case it will be a Controller:

To make this path work I need to map this route:
using Sitecore.Pipelines; | |
using System.Web.Mvc; | |
using System.Web.Routing; | |
namespace MyProject.Pipelines | |
{ | |
public class RegisterRoutes | |
{ | |
public void Process(PipelineArgs args) | |
{ | |
RouteTable.Routes.MapRoute("SimpleField", "myFields/SimpleField/Render", new { controller = "SimpleField", action = "Render" }); | |
} | |
} | |
} |
Let’s create our Controller and View:
using Sitecore.Configuration; | |
using Sitecore.Data; | |
using System.Web.Mvc; | |
namespace MyProject.Controllers | |
{ | |
public class SimpleFieldController : Controller | |
{ | |
public ActionResult Render() | |
{ | |
return View("~/Views/SimpleField/Render.cshtml"); | |
} | |
} | |
} |
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,300italic,400italic,600italic,700italic,300,600,700,800" rel="stylesheet"> | |
<link rel="stylesheet" type="text/css" href="/sitecore/shell/themes/standard/default/Default.css" /> | |
<link rel="stylesheet" type="text/css" href="/sitecore/shell/themes/standard/default/Content Manager.css" /> | |
<style> | |
#ll-fields { | |
padding: 10px 10px 10px 10px; | |
} | |
</style> | |
<div id="ll-fields" class="scEditorSections"> | |
<div class="scEditorFieldMarker"> | |
<div class="scEditorFieldLabel">Text:</div> | |
<div> | |
<input type="text" id="ll-text" class="scContentControl scCombobox" /> | |
</div> | |
</div> | |
</div> | |
<script type="text/javascript" src="/scripts/field/field-base.js"></script> | |
<script type="text/javascript" src="/scripts/field/text-field.js"></script> | |
<script> | |
textField.getValue(); | |
document.getElementById('ll-text').onchange = function () { | |
textField.setValue(); | |
}; | |
textField.updateIframeDisplaySettings(); | |
</script> |
As you can see in the View it contains 2 important JS references, they are doing the dirty job:
function fieldBase () {} | |
fieldBase.getParentIframe = function () { | |
var iframes = window.parent.document.getElementsByTagName('iframe'); | |
var parent; | |
Array.prototype.forEach.call(iframes, function (el, i) { | |
if (fieldBase.getIframeDocument(el) === window.document) { | |
parent = el; | |
return; | |
} | |
}); | |
return parent; | |
}; | |
fieldBase.getIframeDocument = function (iframe) { | |
return iframe.contentDocument || iframe.contentWindow.document; | |
}; |
function textField() { } | |
textField.setValue = function () { | |
fieldBase.getParentIframe().setAttribute('sc_value', document.getElementById('ll-text').value); | |
} | |
textField.getValue = function () { | |
document.getElementById('ll-text').value = fieldBase.getParentIframe().getAttribute('sc_value'); | |
} | |
textField.updateIframeDisplaySettings = function () { | |
var parentIframe = fieldBase.getParentIframe(); | |
parentIframe.style = "height: 87px"; | |
parentIframe.scrolling = "no"; | |
} |
At the end the result is this:

Conclusion
After the base functions are created easy to use this because you have the whole control of your field (design, behaviour). I would suggest this solution if you need a complex field (like you have more fields depend on each other). So I already mentioned at the beginning you can find here a more complex field resolved by iframe: https://github.com/ALLWIN-Informatics/Allwin.Sitecore.Modules.LiveList