Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Bo Jacobsen 606 posts 2404 karma points
    Aug 16, 2017 @ 07:42
    Bo Jacobsen
    0

    How to make a custom Forms property with prevalues

    Hi all.

    I cant find any documentation on how to create a custom Forms property with prevalues.

    Can anyone help?

  • Bo Jacobsen 606 posts 2404 karma points
    Aug 21, 2017 @ 11:15
    Bo Jacobsen
    0

    I found out.

    There is a good guide here http://denisemdb.com/learn/umbraco-forms-custom-fieldtype/

    I will post an exsample, others can use if they where stuck like i was.

  • Bo Jacobsen 606 posts 2404 karma points
    Aug 21, 2017 @ 17:42
    Bo Jacobsen
    101

    CustomFieldType .cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Web;
    using umbraco;
    
    namespace my.webapplication.forms
    {
        public class CustomFieldType : Umbraco.Forms.Core.FieldType
        {
            // Prevalues where we use the dropdownlist from ~/App_plugins/UmbracoForms/Backoffice/SettingTypes/dropdownlist.html
            [Umbraco.Forms.Core.Attributes.Setting("Color", alias = "color", description = "Choose color", prevalues = "Red,Green,Blue", view = "dropdownlist")]
            public string Color { get; set; }
    
            // Constructor
            public CustomFieldType()
            {
                // Mandatory
                this.Id = new Guid("DE56846B-55B0-41AB-93AE-96CA980BC8C3");
                this.Name = "Google Recaptcha v2";
                this.Description = "Google Recaptcha v2 api";
                this.Icon = "icon-eye color-orange";
                this.DataType = Umbraco.Forms.Core.FieldDataType.String;
    
                // Optional          
                this.HideField = false;
                this.HideLabel = false;
                this.SortOrder = 10;
                this.SupportsPrevalues = false;
                this.SupportsRegex = true;
    
                // Name of view in  ~/Views/Partials/Forms/Fieldtypes/ if anything else than FieldType.CustomFieldType.cshtml
                this.FieldTypeViewName = "CustomFieldType.thatRocks.cshtml";
            }
    
            // Validate field value.
            public override IEnumerable<string> ValidateField(Form form, Field field, IEnumerable<object> postedValues, HttpContextBase context)
            {
    
                var errorList = new List<string>();
    
                if(field.Mandatory && !postedValues.Any())
                {
                    errorList.Add("Field is mandatory");
                }
    
                return errorList;
            }
    
    
            // Other overrideable methods, that are worth knowing.
            public override IEnumerable<object> ProcessSubmittedValue(Field field, IEnumerable<object> postedValues, HttpContextBase context)
            {
                return base.ProcessSubmittedValue(field, postedValues, context);
            }
    
            public override IEnumerable<object> ConvertFromRecord(Field field, IEnumerable<object> storedValues)
            {
                return base.ConvertFromRecord(field, storedValues);
            }
    
            public override IEnumerable<object> ConvertToRecord(Field field, IEnumerable<object> postedValues, HttpContextBase context)
            {
                return base.ConvertToRecord(field, postedValues, context);
            }
        }
    }
    

    ~/Views/Partials/Forms/Fieldtypes/CustomFieldType.thatRocks.cshtml

    @model Umbraco.Forms.Mvc.Models.FieldViewModel
    @{
        var color = Model.AdditionalSettings.FirstOrDefault(x => x.Key == "Color");
        <input type="text" class="@color" name="@Model.Name" id="@Model.Id" value="@Model.Value" />
    }
    

    ~/App_plugins/UmbracoForms/Backoffice/FieldTypes/CustomFieldType.html

    <input type="text" class="field.settings.Color" value="" />
    
  • Karen Worth 47 posts 140 karma points
    Aug 06, 2020 @ 12:35
    Karen Worth
    0

    After a few days of head scratching I've managed to create a working fileupload Umbraco.forms.fieldtype with prevalue settings that can be manipulated by the form creator (in this instance file type and file size settings).

    If anyone is puzzling how to do this, let me know I will post the code. Happy to! (quite simple when you know how!)

  • Stefan Orr 6 posts 76 karma points
    Aug 18, 2020 @ 22:49
    Stefan Orr
    0

    Hi Karen,

    I would love to see how you did this. I'm trying to create a dropdownlist that sets prevalues from an external database, but reads from the database each time as the caching done with the current implementation of prevalue data is messing things up for me.

    Thanks,

  • Karen Worth 47 posts 140 karma points
    Aug 19, 2020 @ 07:52
    Karen Worth
    0

    Hi Stefan, that does sound tricky. I am hardcoding the prevalues for my fileupload fieldtype, which is easier. I think you would need to create a custom view for the prevalues that can handle the database work inline:

    So set up the reference for the prevalues like so (at the top of your custom field type class in fieldtype.cs) [Umbraco.Forms.Core.Attributes.Setting("preVals", alias = "prevals", prevalues = "", description = "my prevals description", view = "customddlprevals.html"]

    public string preVals{get;set;}

    The customddlprevals.html must be saved in App_Plugins/UmbracoForms/Backoffice/SettingsTypes You prob already know this!

    but then use an angular controller on customddlprevals.html to reference the class that will grab the required data from the database. I've not had to do this myself, we've only had to call in values from a database for the cshtml page, which is very straightforward.

    However, I think the solution provided in this stackoverflow answer I found here maybe a useful guide for how to set up your external class / angular controller and html (customddlprevals.html in this instance).

    https://stackoverflow.com/questions/45026383/how-to-call-external-class-into-angularjs-controller/45028512

    I will post full examples of my code for the custom file uploader with file size and file type pre as soon as I can in case they are helpful as well.

  • Karen Worth 47 posts 140 karma points
    Aug 19, 2020 @ 14:11
    Karen Worth
    0

    I've tried to show all my code to complete the custom file upload with prevalue editor settings below, had a lot of difficulty getting this to display in a way that makes sense. but essentially all the following should be in black boxes, to represent code (except for my comments).

    To start, add the following to the App_Data/FieldTypes.cs:

    public class myFUwithPre : FileUpload { //start parenthesis

    public myFUwithPre()

    { //start myFUwithPre() function
        this.Id = new Guid("12a59782-a654-406c-bd95-28e2761ba43f");
        this.Name = "myfuwithpre";
        this.Description = "Custom File uploader";
        this.Icon = "icon-forms-stackoverflow color-deep-purple";
        this.DataType = FieldDataType.String;
        FieldTypeViewName = "FieldType.myFUwithPre.cshtml";
    }
    
    //prevalue settings
    [Umbraco.Forms.Core.Attributes.Setting("preVals", alias = "prevals", prevalues = "pdf,doc,jpg,png,xls", description = "Set file type restriction", view = "bsfupre")]
    public string preVals { get; set; }
    
    [Umbraco.Forms.Core.Attributes.Setting("fileSize", alias = "filesize", prevalues = "1,2,5,10,15", description = "Set file size restriction", view = "bsfupresize")]
    public string fileSize { get; set; }
    
    private string _myFileType;
    private string _objExt;
    private string _objMime;
    private string _checkFT;
    private bool _bcont = true;
    private bool _isX = false;
    private string _invalidMessage = "Invalid upload type or size: ";
    private int _maxFileSize = 0;
    public override IEnumerable<string> ValidateField(Form form, Field field, IEnumerable<object> postedValues,HttpContextBase context)
    {
        IList<HttpPostedFileBase> files = context.Request.Files.GetMultiple(field.Id.ToString());
        foreach(HttpPostedFileBase file in files)
        {
    
            //evaluate the file type to upload
            _objExt = System.IO.Path.GetExtension(file.FileName);
            _objMime = file.ContentType;
            _myFileType = preVals;
            _checkFT = "application/" + _myFileType;
            bool bErr = false;
            int mbytes = 1048576;
    
    
            if (_myFileType != "" || _myFileType != null)
            {
                //set if check for doc or xls filetype//
                if(_myFileType =="xls" || _myFileType == "doc")
                {
                    _isX = true;
                }
                //set extension dot
                _myFileType = "." + _myFileType;
    
                if ((_objExt != _myFileType) && (_objMime != _checkFT || _objMime != "application/unknown"))
                {
                    if (_isX)
                    {
                        // first run again against with x ext
                        string myXFileType = _myFileType + "x";
                        _checkFT = "application/" + myXFileType;
    
                        if ((_objExt != myXFileType) && (_objMime != _checkFT || _objMime != "application/unknown"))
                        {
                            //set message 
                            _invalidMessage = _invalidMessage + "Please upload " + _myFileType + " or " + myXFileType + " file type. ";
                            bErr = true;
                        }
    
                    }else
                    {
                        bErr = true;
                        //set invalid message
                        _invalidMessage = _invalidMessage + "Please upload  " + _myFileType + " file type. ";
                    }
                }
            }
    
            if (fileSize != null && fileSize != "")
            {
                _maxFileSize = Int16.Parse(fileSize);
                //calculate maxfilesize in bytes:
                _maxFileSize = (_maxFileSize * mbytes);
                if(file.ContentLength > _maxFileSize)
                {
                    _invalidMessage = _invalidMessage + "File cannot exceed " + fileSize + "mb";
                    bErr = true;
                }
            }
            if (bErr)
            {
                return new[]
                { _invalidMessage};
            }
        }
        return Enumerable.Empty<string>();
    }  //end function
    

    } //end parenthesis

    Again apologies for the display on this this website had it's own ideas about how to display this, so I hope it still makes sense!

    Add the custom view FieldType.myFUwithPre.cshtml in Views/Partials/Forms/Fieldtypes/Themes/Default/Fieldtypes with the following :

    @using Umbraco.Forms.Mvc @model Umbraco.Forms.Mvc.Models.FieldViewModel

    @{ 
        var settings = Model.AdditionalSettings;
        var hasFileSize = (settings.ContainsKey("fileSize") && !string.IsNullOrEmpty(settings["fileSize"]));
        var hasFileType = (settings.ContainsKey("preVals") && !string.IsNullOrEmpty(settings["preVals"]));
        var strMessage = "Uploads restricted to:  ";
    
    }
    <input type="file" class="@Html.GetFormFieldClass(Model.FieldTypeName)" name="@Model.Name" id="@Model.Id" multiple
           @if (Model.Mandatory) { <text> data-val="true" data-val-required="@Model.RequiredErrorMessage" </text>  } />
    

    @if (Model.Values != null && Model.Values.Any()) {

    Current File/s:
    @foreach (string filePath in Model.Values) { var fileName = filePath.Split('/').Last();

            <a>@fileName</a><br />
            <input type="hidden" name="@(Model.Name)_file_@(fileName)" value="@filePath" />
        }
    </p>
    

    }

    @if (hasFileType || hasFileSize){

    if (hasFileType){ strMessage = strMessage + " " + settings["preVals"].ToString() + " file type."; }

    if (hasFileSize) { strMessage = strMessage + " " + settings["fileSize"].ToString() + "mb max file size."; }

    <p style="color:maroon !important;"><label for="@Model.Name">@strMessage</label> </p> } 
    

    Again sorry for the weird display can't seem to get this site to render all the code in a black box!

    Finally under App_Plugins/UmbracoForms/Backoffice/Common/FieldTypes create an html file (in this instance this should reflect the name you have given your custom control in the declaration so in this instance the file is called myfuwithpre.html.

    < input tabindex="-1" type="file" />

    < div class="inline-editor inline-textarea fieldset-prevals" ng-model="field.settings.preVals" placeholder="Please select required file type (leaving it blank will default to all allowed)"> Required file type: {{field.settings.preVals}}

    < /div> < div class="inline-editor inline-textarea fieldset-filesize" ng-model="field.settings.fileSize" placeholder="Please select required maximum file size" >
    File size restricted to: {{field.settings.fileSize}} mb < /div > This gives the form author a message to show what file type and size options have been selected

  • Karen Worth 47 posts 140 karma points
    Aug 20, 2020 @ 10:15
    Karen Worth
    0

    Oops forgot to mention you will need to add two html files to App_Plugins/UmbracoForms/BackOffice/common/SettingsTypes: in this instance I've called one bsfupre.html (that handles the prevalues for filetypes) and the other bsfupresize.html (these are referenced in the view properties of the Umbraco.Forms.Core.Attributes.Setting(s).

    The script for bsfupre.html is:

    < ul > < li class="radiobuttonlist radio-inline fieldset-prevals" style="list-style-type:none !important;" ng-model="field.settings.preVals" ng-repeat="pre in setting.prevalues" > < label class="radio" > < input type="radio" name="checkboxlist" ng-model="setting.value" value="{{pre}}" /> {{pre}} < /label > < /li >< /ul >

    // and the bsfupresize.html is:

    < ul > < li class="radiobuttonlist radio-inline fieldset-filesize" style="list-style-type:none !important;" ng-model="field.settings.fileSize" ng-repeat="fs in setting.prevalues" > < label class="radio" > < input type="radio" name="radiobuttonlist" ng-model="setting.value" value="{{fs}}" /> {{fs}} mb < /label > < /li >< /ul >

    I hope that is readable! I had to put a space after each < and before each > in order to get it to render on this web page.

  • Stefan Orr 6 posts 76 karma points
    Aug 20, 2020 @ 21:48
    Stefan Orr
    1

    Hi Karen,

    Thanks so much for this, it's very helpful. I kind of did something similar which was to create a helper class that queried data from the external source and then I used this in the fields view to get the prevalues and then populate the models preview values. I prefer your solution to this one though as I feel it better separates all the moving parts.

    Thanks heaps for the response.

  • Karen Worth 47 posts 140 karma points
    Aug 24, 2020 @ 06:57
    Karen Worth
    0

    You are most welcome! Very glad that it helped.

Please Sign in or register to post replies

Write your reply to:

Draft