Coder Social home page Coder Social logo

Comments (29)

hfloyd avatar hfloyd commented on August 17, 2024 1

For those of you using Archetype with ModelsBuilder, you might consider trying the "Nested Content" package. It is just as quick and easy to create "custom" datatypes as using Archetype. And since Nested Content uses Doctypes as the "blueprints", and ModelsBuilder uses Doctypes, it's easy to have a model generated for the properties defined on a Nested Content automatically.

An example scenario:

The Doctype "Homepage" has a NestedContent of type "ResourceBox" (which has some properties: Title, Description, Link, Image, etc.)

By default, ModelsBuilder will create a model for ResourceBox, since it is defined as a DocType, and just like for other Doctypes, we can create a custom partial to add or change the way properties are returned.

The "HompageResourceBoxes" property on the "Homepage" model is generated automatically as:

/// <summary>Resource Boxes</summary>
[ImplementPropertyType("HomepageResourceBoxes")]
public object HomepageResourceBoxes
{
    get { return this.GetPropertyValue("HomepageResourceBoxes"); }
}

So, we override that with a custom property implementation:

/// <summary>Resource Boxes</summary>
[ImplementPropertyType("HomepageResourceBoxes")]
public IEnumerable<ResourceBox> HomepageResourceBoxes
{
    get
    {
        var items = this.GetPropertyValue<IEnumerable<IPublishedContent>>("HomepageResourceBoxes");
        return items.ToResourceBoxes();
    }
}

...

public static IEnumerable<ResourceBox> ToResourceBoxes(this  IEnumerable<IPublishedContent> Content)
{
    var list = new List<ResourceBox>();

    foreach (var item in Content)
    {
        var rb = new ResourceBox(item);
        list.Add(rb);
    }

    return list;
}

Now you can access these strongly-typed in a view like:

@if (Model.Content.HomepageResourceBoxes.Any())
{
    foreach (var box in Model.Content.HomepageResourceBoxes)
    {
        <div class="resourceitem">
            <p><a href="@box.Link.Url">@box.ResourceBoxTitle</a></p>
            @Html.Raw(box.Description)                
        </div>
    }
}

Just an alternative to consider.

from modelsbuilder.original.

zpqrtbnk avatar zpqrtbnk commented on August 17, 2024

I do understand the need but I fail to see how I could generate that Archetype-specific code... not mentionning that every custom datatype will then want me to generate specific code... so I'd end up generating models for custom datatypes...
Where should I get the Slider class definition from? That's Archetype-specific.
That being said... we can discuss how to add some extension points in the ModelsBuilder so that datatypes can provide their own models. When hitting a property type, we would want to check if there's a custom builder for the corresponding datatype, and use it to get

  • the returned CLR type (here, IEnumerable)
  • the property getter code
  • extra code (here, the Slider class)

And then it would be up to Archetype to figure out how to implement the extension point.
So we maintain separation, modularity, etc.
Making sense? Suggestions?

from modelsbuilder.original.

leekelleher avatar leekelleher commented on August 17, 2024

Jumping in on this, just to throw an idea out there.

Would it be possible in the ModelsBuilder to access the PropertyValueConverter for a given property-editor? If so, then the PropertyValueType attribute could be used to get the object type?
See Archetype's ArchetypeValueConverter class.

I can't comment on @jbreuer's Slider code - that's project specific. In those cases I would use a custom TypeConverter (as .GetPropertyValue<T> would pass the ArchetypeModel to it).

from modelsbuilder.original.

jbreuer avatar jbreuer commented on August 17, 2024

I like the idea of the ModelsBuilder to have an extension point so that datatypes can provide their own model.

In that case Archetype could use that extension point and return the correct model and have it go through it's own converter. The ModelsBuilder would than generate something like this for the Archetype Slider datatype.

[ImplementPropertyType("slider")]
public Slider Slider
{
    get { return this.GetPropertyValue<Slider>("slider"); }
}

from modelsbuilder.original.

kgiszewski avatar kgiszewski commented on August 17, 2024

@zpqrtbnk Agreed. I wouldn't code data type specific code, but the ability to add extension points seems very useful.

from modelsbuilder.original.

jbreuer avatar jbreuer commented on August 17, 2024

Would those extension points be part of the ModelsBuilder or part of the Umbraco core? If they are part of the ModelsBuilder it would mean that Archetype probably needs a reference to the ModelsBuilder unless you use reflection.

from modelsbuilder.original.

kgiszewski avatar kgiszewski commented on August 17, 2024

I'd keep them separate and maybe propose implementing an interface that ModelsBuilder exposes and use reflection to grab any implementations in memory.

That way Archetype doesn't need to know about ModelsBuilders, ModelsBuilders doesn't need to know about Archetype and a third bit of code marries the two.

from modelsbuilder.original.

zpqrtbnk avatar zpqrtbnk commented on August 17, 2024

@leekelleher - the ModelsBuilder already accesses the property's PropertyValueConverter to get the CLR type returned by the property, as indicated by the PropertyValueType attribute, or by the GetPropertyValueType() method of the IPropertyValueConverterMeta, if implemented.

So if the Archetype property value converter can tell us what exact CLR type it would return for a given property, we would use it in ModelsBuilder. Ideally in @jbreuer situation, Archetype converter would indicate that it converts to IEnumerable<Slider> and we would generate the following code:

[ImplementPropertyType("slider")]
public IEnumerable<Slider> Slider
{
  get
  {
     return = this.GetPropertyValue<IEnumerable<Slider>>("slider");
  }
}

That way, ModelsBuilder, Umbraco and Archetype are completely independent. But it means that Archetype has to be able to implement the proper converter, that the converter has a way to figure out the specific CLR type it returns, and that the Slider class has to be generated somehow, somewhere.

Thinking of it, I think that's the cleanest way to do it.

from modelsbuilder.original.

jbreuer avatar jbreuer commented on August 17, 2024

This is more related to Archetype than the models builder, but it's related to this topic. When there is some way to generate models for Archetype it might be good to also think about nested Archetypes. So you first need to generate models for the Archetype datatypes that don't have any nested Archetypes and than for the ones that do. That way the Archetype model can also have another nested Archetype model as an IEnumerable property.

from modelsbuilder.original.

jbreuer avatar jbreuer commented on August 17, 2024

Now that the grid editor for Umbraco 7.2 is getting closer it might be nice to kick this topic again. It would be cool if you could also generate models for the grid editor :-).

from modelsbuilder.original.

hfloyd avatar hfloyd commented on August 17, 2024

+1 for "also generate models for the grid editor" :-)

from modelsbuilder.original.

MrMattTaylor avatar MrMattTaylor commented on August 17, 2024

I was just looking at the Grid Layout myself and hoping the model builder would work with it.
I'm guessing it may be some time off.

from modelsbuilder.original.

Lechus avatar Lechus commented on August 17, 2024

+1 Grid editor in u7.2

from modelsbuilder.original.

hfloyd avatar hfloyd commented on August 17, 2024

Regarding the Grid... I found that the 'Skybrud.Umbraco.GridData' library works well.

It really isn't very much work to override those Grid properties in the customized partial class:

    using Skybrud.Umbraco.GridData;
    using Umbraco.Web;
    using Zbu.ModelsBuilder;

    /// <summary>
    /// The text page.
    /// </summary>
    public partial class TextPage
    {
        /// <summary>
        /// Gets the page body text as a grid object
        /// </summary>
        [ImplementPropertyType("PageBodyText")]
        public GridDataModel PageBodyText
        {
            get
            {
                return this.GetPropertyValue<GridDataModel>("PageBodyText");
            }
        }
    }

from modelsbuilder.original.

micklaw avatar micklaw commented on August 17, 2024

Hey Folks,

I know this is an old post, but I noticed some nice changes in the Ditto develop branch which make implementing POCO Archetypes, or whatever really for that matter, quite easy. I created a quick repo (https://github.com/micklaw/Ditto.Resolvers) PoC today which shows using POCOs for Archetypes and Nested Archetypes via Ditto.

This does currently only hang from the develop branch of Ditto, so is not practical for use just now, but hopefully when or if those changes are merged in it should start working or be a good started for implementation.

Cheers

from modelsbuilder.original.

kgiszewski avatar kgiszewski commented on August 17, 2024

I'm late to the Ditto party, but will be testing the main package soon so I can formulate an intelligent response to this :)

from modelsbuilder.original.

zpqrtbnk avatar zpqrtbnk commented on August 17, 2024

Planning to discuss the whole modeling thing with co-modelers at CG15!

from modelsbuilder.original.

kgiszewski avatar kgiszewski commented on August 17, 2024

I'll stay tuned :)

from modelsbuilder.original.

kgiszewski avatar kgiszewski commented on August 17, 2024

@micklaw Thanks for posting that repo for making Ditto and Archetype work together. However it's not clear to me what your code does. Meaning if I just create a POCO like so:

using Archetype.Models;
using Umbraco.Core.Models.PublishedContent;

namespace MendozaApp.UmbracoExtensions.Wiki.Models
{
    public class WikiTopicModel : PublishedContentModel
    {
        public WikiTopicModel(Umbraco.Core.Models.IPublishedContent content) : base(content) { }

        public string Content { get; set; }

        public ArchetypeModel QuickLinks { get; set; }
    }
}

I'm then able to access the model on the template like the following without using any additional code:

var pageModel = Model.Content.As<WikiTopicModel>();

@foreach (var x in pageModel.QuickLinks)
{
        <div>@x.GetValue("someProperty")</div>

}

Does your code map the Archetype properties as well to a model?

Sorry for the questions.

from modelsbuilder.original.

micklaw avatar micklaw commented on August 17, 2024

Don't be sorry, I haven't exactly written pages of docs =)

Yeah, that's the idea. There's a brief explanation on the read me on the GitHub page. Basically there will be a POCO for your DocType (Ditto) and also a POCO for your Archetype.

To bind an Archetype on your DocType class you will create a public property and decorate that with an Attribute:

[ArchetypeResolver("DifferentPropertyName")]
public List List { get; set; }

CustomArchetype in this instance would be your Archetype POCO and its fields would map to the properties you have created in your Archetype. As long as CustomArchetype inherits from ArchetypeFieldsetModel and it has the same name as the fieldset alias in the datatype it should just work.

I'll knock up an example when the kids are asleep. Couldn't do it one handed ;)

from modelsbuilder.original.

kgiszewski avatar kgiszewski commented on August 17, 2024

Ok sounds good. Not sure if @zpqrtbnk wants this thread to continue on his project, but thanks for looking into this.

from modelsbuilder.original.

micklaw avatar micklaw commented on August 17, 2024

@kgiszewski I've added a sample project to the solution to show how this works, hopefully it gives the gist. I think your right, this chat should probably be moved to the new repository so were not spamming. Anything else you want to know just add as a Issue on https://github.com/micklaw/Ditto.Resolvers and i'll get back to you asap. I'll also get cracking on some docs.

from modelsbuilder.original.

zpqrtbnk avatar zpqrtbnk commented on August 17, 2024

@kgiszewski I'm happy having this thread here ;-) But if you think of a more appropriate place, just move it there and post the link here. It's a cross-solutions discussion anyway.

Highly interesting to me though, because:

  • Models generation and caching. With the (currently experimental) NuCache, the actual IPublishedContent objects will be cached (and not recreated from Xml all the time). And if the models factory is used, it's the model itself that is cached. Brings flexibility and performance, but requires a clarification of what can be done, and what cannot, with models.
  • Nested/Detached/Virtual/YouNameIt content. At the moment Core is focused on IPublishedContent -- our own, those that we manage, those that are nodes in the database and have an ID, etc. But with Archetype, the Grid, and other projects, it becomes obvious that solutions should exist for a somewhat unified way of dealing with content, whether it's a "true node" or only a "part" of a true node.

from modelsbuilder.original.

LoganPeck avatar LoganPeck commented on August 17, 2024

Hi guys, on the subject of Archetype & Models Builder working nicely together, I have put together a little add-on that takes care of it on data type save. It will create a strongly typed model (cs file) based off of the Archetype prevalues. It also overrides the ArchetypeValueConverter so Archetype can tell the Models Binder what Type to expect. https://github.com/LoganPeck/Umbraco-Archetype-Model-Binder-Add-On

This is my first time contributing code anywhere so my documentation/coding style may be off. Feel free to check it out and let me know if there are any suggestions or questions. Also feel free to contribute as well!

from modelsbuilder.original.

jbreuer avatar jbreuer commented on August 17, 2024

Thanks for the advice. I've also switched to Nested Content and it works really great! https://gist.github.com/jbreuer/0a5996e5e6bf881ce847

from modelsbuilder.original.

zpqrtbnk avatar zpqrtbnk commented on August 17, 2024

Quick comment: I don't think the ModelsBuilder will be able to "generate" models for Archetype anytime soon. The good thing with packages such as NestedContent is that they rely on the already-existing content type system, and therefore can have models easily generated.

Next step is to add a way so that we can easily figure out the model type that would be returned by a nested content property. Which, I think, is feasible. There might be a way to generate the IEnumerable<ResourceBox> above directly. Work-in-progress...

from modelsbuilder.original.

hfloyd avatar hfloyd commented on August 17, 2024

That would be great, Stephan! I don't use so many NC properties that the customizing work is too much for me, but those who do use them heavily would certainly benefit from a helping hand :-)

from modelsbuilder.original.

shokri-navid avatar shokri-navid commented on August 17, 2024

please add this feature....

from modelsbuilder.original.

zpqrtbnk avatar zpqrtbnk commented on August 17, 2024

Been a long time - closing.

from modelsbuilder.original.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.