How do I get the Name of a block in EpiServer? - episerver

How do I get the name, set in the CMS, of a certain block in an MVC view?
I guess that it should be #Model.Name but I can't find it.

You have to cast your block instance to IContent to access the Name property.
For details on why, you can have a look at: Episerver - Why BlockData doesn't implement IContent

The syntax to get the Name property is
(Model as IContent).Name
or
((IContent)Model).Name
Be careful with this cast as handling a Block which is a property as opposed to a ContentReference will not work and throws an exception.

If you want to display the name in the view - you can cast the model inside PropertyFor:
#Html.PropertyFor(m => ((IContent)m).Name)

Related

Change name, type and value of a page or block property in Episerver

We often need to refactor existing pages and blocks due to new requirements. Usually one or more properties are to be replaced by one or more new properties. Existing pages and blocks need to keep on working and it is not uncommon that settings made using the old properties need to affect the settings of the new properties. Creating new pages or blocks to replace existing ones is not an option - unless it can be automated.
Simple example #1: The old Boolean property UseDarkBackgroundColor is replaced by the new string property BackgroundColor. If UseDarkBackgroundColor was set, BackgroundColor should be set to a specific color.
Simple example #2: The old Boolean property IsWide is replaced by the new property IsNarrow (basically flipping name and value). If IsWide was true, IsNarrow should be false and vice versa.
In the past we have solved this by updating the Episerver database using an SQL script. I find this kind of scary and I would therefore like to find a better approach.
The following article gives me some hope: https://world.episerver.com/documentation/developer-guides/CMS/Content/Refactoring-content-type-classes#API
The information under the section "Renaming a content type by API" is easy to understand and when testing it the result was as expected. However, the text under the section "Changing the type for a property" is next to gibberish to me. I don't even know where to start, even after a lot of googling.
Does anybody know of an example that shows how to change the type (and value) of a property in Episerver without an SQL script?
We never change types for an existing property, but rather we introduce a new property, hide the old one from the UI, and (if applicable) implement a custom getter for the new property so that it uses the old property as "fallback" until an editor has published content with the new property.
Sometimes we migrate the old property value to the new property through some type of batch job, and then delete the old property.
We never manipulate the database directly.
Also check out migration steps, commonly used if you for example need to rename a property: https://www.jondjones.com/learn-episerver-cms/episerver-developers-tutorials/importing-content-into-episerver-programmatically/episerver-migration-steps-explained/
Just want to add to Ted's answer that you can hide the old property and use an existing value for the new by providing a fallback/default value in the getter:
[ScaffoldColumn(false)]
[Obsolete("BackgroundColor should be used now")]
public virtual bool UseDarkBackgroundColor { get; set; }
public virtual string BackgroundColor
{
get { return this.GetPropertyValue(block => block.BackgroundColor, UseDarkBackgroundColor ? "Black" : null); }
set { this.SetPropertyValue(block => block.BackgroundColor, value); }
}

How to use containerRegistry.RegisterForNavigation with a generic ViewModel?

I have an app with two regions, one serving as a selector for data type (called NavigationPane) and the other one as a setter view for that data type (called SimulationPane). The SimulatorView.xaml I use to fill the SimulationPane has a corresponding SimulatorViewModel which dynamically creates a list of settable properties for TDataType and eventually binds it to a ItemsControl in SimulatorView.xaml. So my ViewModel needs System.Type as input:
I want to set it up as following:
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<TopicSelectorView, TopicSelectorViewModel>("Selector");
containerRegistry.RegisterForNavigation<SimulatorView, SimulatorViewModel<A>>("Simulator_A");
containerRegistry.RegisterForNavigation<SimulatorView, SimulatorViewModel<B>>("Simulator_B"); // and so on..
}
Once I have it registered, I want to be able to call (from other module):
regionManager.RequestNavigate("SimulationPane", $"Simulator_{topicType.Name}");
where topicType is the data type based on user's selection (here: 'A', 'B', and so on).
The problem with this approach is that I end up with just one ViewModel, i.e. the one I registered last. My impression is that that the registration uses some kind of dictionary with view as a key.
What am I doing wrong here? How else can I achieve my goal of being able to provide a type for VM at runtime, and navigate to it?
How else can I achieve my goal of being able to provide a type for VM at runtime, and navigate to it?
Register multiple viewmodels with the same view is not supported in Prism. See #brianlagunas answer on GitHub:
As I said in my reply to your PR, this is not something we will support in Prism. You have a few options, two of which we have already discussed; create a unique view, or have a single VM and load the relevant data.
Why do you need to pass A and B as generic parameters?
I'd have a single SimulatorViewModel and inject a service from which the view model can get the list of parameters to be set by the user. This could be done through reflection (on the simulator type) or a list of parameter descriptors (IReadOnlyCollection<Parameter> ISimulator.Parameters { get; }), whatever you prefer.
When changing the simulator type, you update it in the service and the SimulatorViewModel updates its list of parameters, because it listens to the service's INotifyPropertyChanged.PropertyChanged.

How can I echo the label of a salesforce custom object on a visualforce page?

I want to access the metadata of a custom object and display the name of the custom object. This has been changed from the original and I want my page to always display the name without having to change any code or markup.
A label can be accessed as {!$Label.MyLabel}.
Is there something akin to {!$MyCustomObject.Label}?
Any ideas?
Yes you can do this via the Global Variable $ObjectType i.e.
{!$ObjectType.CustomObjectName__c.Label}
also for these types of questions try the salesforce Beta, salesforce.stackexchange.com

Why using the this.$(selector).method() syntax with backbone?

I have seen this bunch of code in a tutorial:
var searchTerm = this.$('#searchTerm').val().trim();
I would like to understand the utility of the this. in front of the selector, it's the first time i see that.
In a Backbone.View, this.$ gives a scoped version of jQuery. It is in fact equivalent to using this.$el.find which is in turn equivalent to using $(this.el).find.
Anyhow, the reason it is a good idea to use it is that it will only access html elements from within the view's element/rendered template. Thus, you don't have to worry about the rest of the html page and you will always select the element you expect to.
Imagine that you have a view that spawns sub-views and that each of these have an editable field. If you don't use the scoped version of jQuery to get the right editable field, you will have to give a unique id to each of these html elements to make sure you will select the right one when retrieving it's content. On the other hand, if you use the scoped version, you will just have to give this editable field a class attribute and selecting this class will give you a unique element, the right one.
This is the same query as this.$el.find('#searchTerm').val().trim();
You haven't given any context to that code, but assuming it's a method inside a View, this refers to the View object.
this.$ is a shortcut to access jQuery from the View object, and is equivalent to the method this.$el.find.

CakePHP a class that can be used anywhere?

I have a multi-domain site. Depending on the domain the site needs to behave accordingly.
I created a helper called CompanyInfo it has methods such as name(), phone(), email(), etc.
Depending on what domain you are on it returns the correct information.
So for example if I need to display the phone number for a user to call I would use $this->CompanyInfo->phone() and it will display the correct phone number for the user depending on the domain.
Ok, this is all good, but not really relevant. The real issue is, I need this information in more than just the view. Helpers are just for views though. If I want to access this information from a controller I need to create a component to do it.
I really don't want to have a Helper and a Component doing the same thing. I would rather have one class handle it rather than copy and paste logic.
So whats the best way to have a class with methods that can be accessed from the controller or view or even model?
Is it just this kind of static information (name, phonenumber, email, etc) what you need to display? Why not just add them to your configuration in core.php?
Something like
# in core.php
Configuration::write('Company.name', 'Acme Corp.');
Configuration::write('Company.email', 'joe#acme.com');
You can then get this info anywhere you need using
Configuration::read('Company.name');
You can define this variable in your app_controller and then use these variable easily in any of your controller as set these variables from there only.
Call this function in your construct class.
i think that will solve your problem.
You can access model classes from any place this way :
$companyInfoModel = ClassRegistry::init('CompanyInfo');
$phone = $companyInfoModel->phone();
a) you can use libs in cake1.3 for that
b) static model methods which you can pass the content to and which will return the expected value
echo Model::phone($data)

Resources