I have some different members with additional properties like first name, last name, phone and company (using MNTP to pick a "Company" content node).
On Company document type I also have a properties using nuPickers relation labels. However when some members have picked a company, then it doesn't seem to create a relation in database - even a have a Relation type between Content and Member) - and therefore nuPickers doesn't display the relations.
Shouldn't it create the relation between content and member in this case?
If I replace MNTP with nuPickers.XmlPrefetchListPicker then it does create the relation, although it saved an object instead of just a node id.
Nothing else than using MNTP and having an relation types configurated, but I guess it does create the relation then out of the box like when using the picker in nuPickers.
I have and old site in one of the latest releases of Umbraco v4, where the editors can pick different "quotes" or "references" for each page and then I a similar "custom label" property - so it was using MNTP in uComponents.
As I remember I only had the configurate it from backoffice and set up the relation type for that Document (content) to Document (content) relation.
In a old Umbraco 4.11.1 site using uComponents 5.3.0, where I had created an "Relate Page And Quote" relation.
I also created data types "Quote Picker" using MNTP and "Pages with Quotes" using uComponents: Relation Labels
When pages using "Quote Picker" had picked any quotes, then on the quote itself you could see on which pages it had been picked.
When I am doing something similar with a content node and member using nuPickers, it doesn't seem to create the relation using MNTP - but it does create one when using the other pickers in nuPickers.
I have managed to solve it in this way similar to how nuPickers handle it with its different pickers. However when picking a company while create a member and hitting save, it seems it doesn't create the relation - first when I save the member again (after it has been created).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Core;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
namespace My.Library.Events
{
/// <summary>
/// server side event to update relations on change of any member
/// </summary>
public class RelationMappingEvent : ApplicationEventHandler
{
// inspired from nuPickers: https://github.com/uComponents/nuPickers/tree/master/source/nuPickers/Shared/RelationMapping
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
MemberService.Saved += this.MemberService_Saved;
// NOTE: all relations to an id are automatically deleted when emptying the recycle bin
}
private void MemberService_Saved(IMemberService sender, SaveEventArgs<IMember> e)
{
this.Saved((IService)sender, e.SavedEntities);
}
/// <summary>
/// combined event for member
/// </summary>
/// <param name="sender"></param>
/// <param name="savedEntities"></param>
private void Saved(IService sender, IEnumerable<IContentBase> savedEntities)
{
foreach (IContentBase savedEntity in savedEntities)
{
// for each property
foreach (PropertyType propertyType in savedEntity.PropertyTypes.Where(p => p.Alias == "umbracoMemberCompany"))
{
List<int> pickedIds = new List<int>();
int memberId = savedEntity.Id;
var mntpValues = savedEntity.GetValue(propertyType.Alias);
if(mntpValues != null)
{
pickedIds = mntpValues.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToList();
}
UpdateCompanyRelations(memberId, "relateCompanyToMember", pickedIds);
}
}
}
private void SetCompanyRelation(int contentId, int memberId)
{
var rs = ApplicationContext.Current.Services.RelationService;
var areRelated = rs.AreRelated(contentId, memberId, "relateCompanyToMember");
if (!areRelated)
{
//create relation between document (company node) and member
var relType = rs.GetRelationTypeByAlias("relateCompanyToMember");
var r = new Relation(contentId, memberId, relType);
r.Comment = string.Format("Relate document id {0} to member id {1} ", contentId, memberId);
rs.Save(r);
}
}
/// <summary>
///
/// </summary>
/// <param name="contextId">the id of the content, media or member item</param>
/// <param name="propertyAlias">the property alias of the picker using relation mapping</param>
/// <param name="relationTypeAlias">the alias of the relation type to use</param>
/// <param name="pickedIds">the ids of all picked items that are to be related to the contextId</param>
private void UpdateCompanyRelations(int contextId, string relationTypeAlias, List<int> pickedIds)
{
IRelationType relationType = ApplicationContext.Current.Services.RelationService.GetRelationTypeByAlias(relationTypeAlias);
if (relationType != null)
{
// get all relations of this type
List<IRelation> relations = ApplicationContext.Current.Services.RelationService.GetAllRelationsByRelationType(relationType.Id).ToList();
// filter down potential relations, by relation type direction
if (relationType.IsBidirectional)
{
relations = relations.Where(x => x.ChildId == contextId || x.ParentId == contextId).ToList();
}
else
{
relations = relations.Where(x => x.ChildId == contextId).ToList();
}
// check current context is of the correct object type (as according to the relation type)
if (ApplicationContext.Current.Services.EntityService.GetObjectType(contextId) == UmbracoObjectTypesExtensions.GetUmbracoObjectType(relationType.ChildObjectType))
{
// for each picked item
foreach (int pickedId in pickedIds)
{
// check picked item context if of the correct object type (as according to the relation type)
if (ApplicationContext.Current.Services.EntityService.GetObjectType(pickedId) == UmbracoObjectTypesExtensions.GetUmbracoObjectType(relationType.ParentObjectType))
{
// create relation for each picked company
SetCompanyRelation(pickedId, contextId);
}
}
}
// delete any relations that not are in picked ids
if (relations.Any())
{
foreach (IRelation relation in relations)
{
if(pickedIds == null || !pickedIds.Contains(relation.ChildId))
{
ApplicationContext.Current.Services.RelationService.Delete(relation);
}
}
}
}
}
}
}
Yes, you are correct. uComponents had a data-type which would 'watch' another picker and wire it up to relations, but this changed in nuPickers - now each picker can update relations directly. (Perhaps this change wasn't so sensible ? but it does avoid creating two data-types).
My guess on your current issue, could be that the relation isn't created on first save, as there isn't yet an id for the member being created ?
Create relation between content node and member
I have some different members with additional properties like first name, last name, phone and company (using MNTP to pick a "Company" content node).
On Company document type I also have a properties using nuPickers relation labels. However when some members have picked a company, then it doesn't seem to create a relation in database - even a have a Relation type between Content and Member) - and therefore nuPickers doesn't display the relations.
Shouldn't it create the relation between content and member in this case?
If I replace MNTP with nuPickers.XmlPrefetchListPicker then it does create the relation, although it saved an object instead of just a node id.
I am used Umbraco 7.4.3 and nuPickers 1.5.3
/Bjarne
Hi Bjarne,
When using the MNTP to pick a company on a member, what are you using to create the relationship ?
Hi Hendy
Nothing else than using MNTP and having an relation types configurated, but I guess it does create the relation then out of the box like when using the picker in nuPickers.
I have and old site in one of the latest releases of Umbraco v4, where the editors can pick different "quotes" or "references" for each page and then I a similar "custom label" property - so it was using MNTP in uComponents.
As I remember I only had the configurate it from backoffice and set up the relation type for that Document (content) to Document (content) relation.
Hi Hendy
In a old Umbraco 4.11.1 site using uComponents 5.3.0, where I had created an "Relate Page And Quote" relation.
I also created data types "Quote Picker" using MNTP and "Pages with Quotes" using uComponents: Relation Labels
When pages using "Quote Picker" had picked any quotes, then on the quote itself you could see on which pages it had been picked.
When I am doing something similar with a content node and member using nuPickers, it doesn't seem to create the relation using MNTP - but it does create one when using the other pickers in nuPickers.
/Bjarne
Should nuPickers also create relation, when using MNTP like it does for the other pickers? https://github.com/uComponents/nuPickers/blob/0c8891cd94b6e073adc95cdf10d3203f6bce7881/source/nuPickers/Shared/RelationMapping/RelationMappingEvent.cs
In uComponents it did create the relation, when using MNTP as in the example mentioned before, where MNTP was in core.
/Bjarne
I have managed to solve it in this way similar to how nuPickers handle it with its different pickers. However when picking a company while create a member and hitting save, it seems it doesn't create the relation - first when I save the member again (after it has been created).
/Bjarne
Hi Bjarne,
Yes, you are correct. uComponents had a data-type which would 'watch' another picker and wire it up to relations, but this changed in nuPickers - now each picker can update relations directly. (Perhaps this change wasn't so sensible ? but it does avoid creating two data-types).
My guess on your current issue, could be that the relation isn't created on first save, as there isn't yet an id for the member being created ?
HTH, Hendy
Hi Hendy
Okay, so in uComponents it seems it always "watch" MNTP after it was included in core of Umbraco.
With nuPickers it only map these relations for its own pickers.
So for now it seems I have to create the relation myself like in the code posted.
Yes, that might be the issues.. not sure if there is a way to ensure the relation is created on first save too?
Update: savedEntity does have an contentTypeId and id
Before it reach UpdateCompanyRelations the memberId is saved in
int memberId = savedEntity.Id;
And the picked node id exists, when it reach this property.
Hmm, but it did seem to create the relation this time on save.
/Bjarne
I came across this page after looking for how to make use of the Relations mapping in v7 for Members, with similar use case in https://our.umbraco.org/projects/backoffice-extensions/media-content-usage/
I have created RelationShips from Content to Member and Member to Content.
Using MNTP by default, doesnt seem to capture the relations, like Bjarne pointed out (had to learn it the hard way...)
Apparently the tutorials/documentation on the net relates to pre v7 for successfull use cases.
For my use case, I'm trying to repliacete the usability of https://our.umbraco.org/projects/backoffice-extensions/media-content-usage/ but for Members instead of Media.
So when I visit a Member, I would like to see the list of Content Nodes (hyperlinks to content nodes).
Since data is already populated, and MNTP used, I cant change to NuPickers directly I think.
Is there a simpler way of using the code posted above, but adopt for Content with specific MemberType("Subscriber") ?
...like:
ContentNode -> MNTP member picker
and when a member page visited, i can see the links of content nodes
is working on a reply...