Copied to clipboard

Flag this post as spam?

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


  • Sam 79 posts 426 karma points
    May 02, 2017 @ 03:47
    Sam
    0

    Create a dropdown options list from content values instead of Data types

    Hello, all

    I am fairly new to umbraco and very new to MVC. I have been able to successfully create contact forms using some online tutorials, one of which allowed a drop-down list to be generated from the data types in back office.

    This is great, but I want to be able to use user entered content values to generate the values in the list. I am hoping there is an easy way to do this.

    the content I want to use would be location contact information. I would like the User to enter location data including name and email address, and the contact form would use the location name to populate the drop-down list, and the selected value from that list be used to send the message to.

    Here is the piece of the Surface Controller that is currently using the Datatype... how can this be changed to use content values?

    // This will generate dropdown values from Data Type Created in Umbraco---- only needed if using dropdownlist
            List<SelectListItem> ListOfLocations = new List<SelectListItem>();
            XPathNodeIterator iterator = umbraco.library.GetPreValues(1091);//Id of Datatype
            iterator.MoveNext();
            XPathNodeIterator preValues = iterator.Current.SelectChildren("companyName", "");
             while (preValues.MoveNext())
            {
                string preValue = preValues.Current.Value;
               ListOfLocations.Add(new SelectListItem
                {
                    Text = preValue,
                    Value = preValue
                });
    
                myModel.ListOfLocations = ListOfLocations;
            }
            // End Dropdown Values
    

    Thanks for your time.

  • Sam 79 posts 426 karma points
    May 03, 2017 @ 19:36
    Sam
    0

    Does anyone have any Info on this?

  • Chris Dunsing 18 posts 83 karma points
    May 03, 2017 @ 20:35
    Chris Dunsing
    0

    When creating things such as dropdowns for forms: I prefer to create sub-nodes that support the dropdown or have a repository structure that I may reference if I need to use it multiple times.

    This allows the user to recreate as many sub items as required. While I can populate a simple foreach loop to iterate through the options for presentation.

        <select>
        @foreach (child in Model.Content.Children){
             <option value="@child.key">@child.friendlyname</option>
        }
        </select>
    

    Then on submit I can look up additional details on the contact based on the option or key submitted.

    //umbraco.NodeFactory.Node
    var node = new Node (submittednodeid);
    node.GetProperty("propertyName").Value 
    
  • Sam 79 posts 426 karma points
    May 03, 2017 @ 20:56
    Sam
    0

    I have the location Information set up as a repository Structure... the user can add as many locations as they like.

    I need the surface controller and model to generate the select list in the view based off of the companyName Values of the document Type.

    this is my current attempt in which I am getting issues using the Get Property method.

     ContactMultiLocModel myModel = new ContactMultiLocModel();
    
            // This will generate dropdown values from Data Type Created in Umbraco---- only needed if using dropdownlist
            List<SelectListItem> ListOfLocations = new List<SelectListItem>();
            var AllLocations = umbraco.uQuery.GetNodeByUrl("/location-information");
            var Location = AllLocations.GetDescendantNodesByType("locationInfo");
    
            XPathNodeIterator iterator = Location.GetProperty("companyName").Value;
            iterator.MoveNext();
            XPathNodeIterator locValues = iterator;
             while (locValues.MoveNext())
            {
                string locValue = locValues.Current.Value;
               ListOfLocations.Add(new SelectListItem
                {
                    Text = locValue,
                    Value = locValue
                });
    
                myModel.ListOfLocations = ListOfLocations;
            }
    
  • Chris Dunsing 18 posts 83 karma points
    May 03, 2017 @ 21:28
    Chris Dunsing
    100

    I think I understand although not familiar with the XpathNodeIterator approach.

    So if it is read only then you should be able to iterate and build your list with the following using linq:

    var locations = AllLocations.ChildrenAsList.Where(n => n.NodeTypeAlias == "myNodeTypeAlias");
    
    foreach (var node in locations)
    {
     ListOfLocations.Add(new SelectListItem
                {
                    Text = node.GetProperty("companyName").Value,
                    Value = node.GetProperty("companyName").Value
                });
    }
    
  • Sam 79 posts 426 karma points
    May 03, 2017 @ 21:42
    Sam
    0

    I get the following errors with the code you supplied:

    CS1929 C# does not contain a definition for 'Where' and the best extension method overload requires a receiver of type

    CS1660 C# Cannot convert lambda expression to type 'string' because it is not a delegate type

  • Chris Dunsing 18 posts 83 karma points
    May 03, 2017 @ 22:11
    Chris Dunsing
    1

    My bad, writing code without a intellisense is a recipe for forum pain :

    var Locations = AllLocations.ChildrenAsList.Where(n => n.NodeTypeAlias=="myNodeTypeAlias");
    
  • Sam 79 posts 426 karma points
    May 04, 2017 @ 05:09
    Sam
    0

    Chris, Thanks so much for your help. I was able to get the form rendered with the values from the document type. If I could pick your brain a little more, I am now having trouble posting the selected value back to Umbraco.

    Here is how the list is generated now:

    ContactMultiLocModel myModel = new ContactMultiLocModel();
    
            // This will generate dropdown values 
            List<SelectListItem> ListOfLocations = new List<SelectListItem>();
            var AllLocations = umbraco.uQuery.GetNodeByUrl("/location-information");
            var Locations = AllLocations.ChildrenAsList.Where(n => n.NodeTypeAlias == "locationInfo");
    
            foreach (var node in Locations)
            {
                ListOfLocations.Add(new SelectListItem
                {
                    Text = node.GetProperty("locationName").Value,
                    Value = node.GetProperty("locationEmail").Value
                });
            }
    
            myModel.ListOfLocations = ListOfLocations;
            // End Dropdown Values
    

    And this is where I am trying to post the Text of the selected item... I will also need the value later on for the "to" email address. As you can see by the question marks I am not even sure I am headed in the right direction.

    if (ModelState.IsValid) // For Field Validation 
            {
                // This will post submittion to Umbraco Database 
                var newContact = Services.ContentService.CreateContent(model.Name + "-" + DateTime.Now, CurrentPage.Id, "contactFormula");
                var myService = ApplicationContext.Services.DataTypeService;
                var SelectedLocation = myService.GetAllDataTypeDefinitions().First(x => x.Name == "Location");
                int SelcetedLocationText = myService.GetPreValuesByDataTypeId(SelectedLocation.Id)???
    
                newContact.SetValue("CFName", model.Name);
                newContact.SetValue("CFEmail", model.Email);
                newContact.SetValue("CFCompany", model.Company);
                newContact.SetValue("CFLocation", SelcetedLocationText);
                newContact.SetValue("CFMessage", model.Message);
                Services.ContentService.SaveAndPublishWithStatus(newContact);
    ...
    
  • Chris Dunsing 18 posts 83 karma points
    May 06, 2017 @ 16:48
    Chris Dunsing
    1

    Hi Sam,

    Sorry for the delay.

    If you are looking to post content back into Umbraco then content service is the right approach.

    The following line does seem out of place. I don't understand what you are trying to get access to with this call:

    int SelcetedLocationText = myService.GetPreValuesByDataTypeId(SelectedLocation.Id)???
    

    Let's rethink our approach to the form submission to allow ourselves more flexibility:

    Change This:

    ListOfLocations.Add(new SelectListItem
                {
                    Text = node.GetProperty("locationName").Value,
                    Value = node.GetProperty("locationEmail").Value
                });
    

    To :

     ListOfLocations.Add(new SelectListItem
                {
                    Text = node.GetProperty("locationName").Value,
                    Value = node.Id // This allows us to lookup a node for further content creation
                });
    

    Now when we submit this form we can pull details about the location and build references/content from the referenced node as needed.

    var location = new Node (submittednodeid);
    
    //attach the name:
    newContact.SetValue("CFLocation", location.Name);
    
    //OR attach the node reference itself if it is a reference/int data type
    newContact.SetValue("CFLocation", location.Id);
    
    //OR iterate through the properties with a stringBuilder and supply richtext.
    var sb = new stringbuilder();
    //for each property in node.properties.
    //append property.value to sb
    //append rich formatting to sb
    //}
    newContact.SetValue("CFLocation", sb.ToString());
    

    Hope this helps please clarify if I didn't grasp what you were after.

  • Sam 79 posts 426 karma points
    May 09, 2017 @ 03:45
    Sam
    0

    That clears it up for me, Thanks for the extra Info.

  • Sam 79 posts 426 karma points
    Sep 03, 2017 @ 04:23
    Sam
    0

    Just for Reference here is the controller after all is working. I was able to create dropdown from content of a specific document type. The selected value was then used to post the data back to umbraco, and controlled where the email was sent to.

    using MyKit.Models;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.Mvc;
    using Umbraco.Web.Mvc;
    using Umbraco.Web;
    using System.Text;
    using System.Net.Mail;
    using umbraco.NodeFactory;
    
    namespace MyKit.Controllers
    {
    public class ContactMultiLocSurfaceController : SurfaceController
    {
    
        public ActionResult ShowForm()// links controller to template/macro
        {
            ContactMultiLocModel myModel = new ContactMultiLocModel();
    
            // This will generate dropdown values 
            List<SelectListItem> ListOfLocations = new List<SelectListItem>();
            var AllLocations = umbraco.uQuery.GetNodeByUrl("/location-information");
            var Locations = AllLocations.ChildrenAsList.Where(n => n.NodeTypeAlias == "locationInfo");
    
            foreach (var node in Locations)
            {
                ListOfLocations.Add(new SelectListItem
                {
                    Text = node.GetProperty("locationName").Value,
                    Value = node.Id.ToString() // This allows us to lookup a node for further content creation
                });
            }
    
            myModel.ListOfLocations = ListOfLocations;
            // End Dropdown Values
    
            return PartialView("ContactMultiLocForm", myModel); // Links to Partial View 
        }
    
    
        public ActionResult HandleFormPost(ContactMultiLocModel model) //Links functions to the form in the partial view...BeginUmbracoForm
        {
            if (ModelState.IsValid) // For Field Validation 
            {
                // This will post submittion to Umbraco Database 
                var newContact = Services.ContentService.CreateContent(model.Name + "-" + DateTime.Now, CurrentPage.Id, "contactFormula");
                var myService = ApplicationContext.Services.DataTypeService;
                int LocationValue = model.Location;
                var LocationNode = new Node(LocationValue);
    
                newContact.SetValue("CFName", model.Name);
                newContact.SetValue("CFEmail", model.Email);
                newContact.SetValue("CFCompany", model.Company);
                newContact.SetValue("CFLocation", LocationNode.Name);
                newContact.SetValue("CFMessage", model.Message);
                Services.ContentService.SaveAndPublishWithStatus(newContact);
    
    
                //This will compose and send email
                var sb = new StringBuilder();
                sb.AppendFormat("<p>Name: {0}</p>", model.Name);
                sb.AppendFormat("<p>Email: {0}</p>", model.Email);
                sb.AppendFormat("<p>Company: {0}</p>", model.Company);
                sb.AppendFormat("<p>Location: {0}</p>", LocationNode.Name);
                sb.AppendFormat("<p>Message: {0}</p>", model.Message);
    
                SmtpClient smtp = new SmtpClient("host.com", 587);
                smtp.Credentials = new System.Net.NetworkCredential("***@website.net", "***");
                smtp.EnableSsl = true;
    
                MailMessage message = new MailMessage();
    
                message.To.Add(LocationNode.GetProperty("locationEmail").Value);
                message.Subject = "Message from Website";
                message.From = new MailAddress(model.Email);
                message.Body = sb.ToString();
                message.IsBodyHtml = true;
    
                try
                {
                    smtp.Send(message);
                }
                catch (SmtpException)
                {
                    TempData["Failed"] = true;
    
                    return RedirectToCurrentUmbracoPage();
                }
    
                TempData["Success"] = true;
    
                return RedirectToCurrentUmbracoPage();
            }
    
            return RedirectToCurrentUmbracoPage();
        }
    
    
    
    }
    }
    

    the Key to this working where the following lines:

    int LocationValue = model.Location;
    var LocationNode = new Node(LocationValue);
    
Please Sign in or register to post replies

Write your reply to:

Draft