I am using the shape tracer in order to use an alternate view of one of my taxonomie fields called location. However unlike other shapes the alternates do not give the option for different display types in this case summary or details. So by changing 1 you change the other. I need to be able to do them independently.
I have a view created see below Fields.Contrib.TaxonomyField-Location.cshtml but as i say this is rendered the same if the display type is details or summary.
How to i overcome this please.
Thanks Jon
I had the same problem not long ago. You can provide your own alternates by implementing a ShapeDisplayEvents class.
Here is an implementation that gives you alternates based on the content type, display type, or both:
public class PartContentTypeAlternateFactory : ShapeDisplayEvents {
public override void Displaying(ShapeDisplayingContext context) {
context.ShapeMetadata.OnDisplaying(displayedContext => {
var shapeType = displayedContext.ShapeMetadata.Type;
var contentItem = displayedContext.Shape.ContentItem;
var displayType = displayedContext.ShapeMetadata.DisplayType;
var contentType = contentItem.ContentType;
displayedContext.ShapeMetadata.Alternates.Add(
String.Format("{0}__{1}", shapeType, displayType));
displayedContext.ShapeMetadata.Alternates.Add(
String.Format("{0}__{1}__{2}", shapeType, (string)contentType, displayType));
});
}
}
You will end up with some extra alternates appearing in the shape tracer, like this:
And you can now use an alternate named Fields.Contrib.TaxonomyField-Location-Summary or Fields.Contrib.TaxonomyField-Location-Detail etc. You can extend this class to add whatever alternates you want.
Edit
I didn't realise you couldn't easily get to the field name, so try something like this - it does something similar to what the UrlAlternatesFactory does, i.e. it loops over the existing alternates and adds the displayType to them. This should give you an alternate that contains both the field name and the display type.
public class PartContentTypeAlternateFactory : ShapeDisplayEvents {
public override void Displaying(ShapeDisplayingContext context) {
context.ShapeMetadata.OnDisplaying(displayedContext => {
var alternates = displayedContext.ShapeMetadata.Alternates.Select(a => a + "__" + displayedContext.ShapeMetadata.DisplayType);
displayedContext.ShapeMetadata.Alternates = displayedContext.ShapeMetadata.Alternates.Union(alternates).ToList();
});
}
}
Related
So I've been playing around with code generation in Dart, and I have a problem resolving Element type in "data" classes. I have 2 data classes, and 2nd one has a type of a 1st one defined as a field.
first.dart:
part 'first.g.dart';
#Data(name="First")
class _First {
}
second.dart:
import 'first.dart';
part 'second.g.dart';
#Data(name="Second")
class _Second {
First first;
}
You might have noticed, that _Second has field First instead of _First. That's because I generate two new classes. These two new classes contain additional functionality, like generated hashCode and some other custom methods I need.
In my Generator class, I need to obtain type string of field first. I'm doing this by fieldElement.type?.getDisplayString().
This works fine for all other non-generated classes, like num for example.
But in case of first field, returned type string is "dynamic".
Is there a way to obtain correct type? Should "First" in this case.
data_generator.dart
class Data extends GeneratorForAnnotation<Data> {
#override
generateForAnnotatedElement(Element element, ConstantReader annotation,
BuildStep buildStep) {
if(element is ClassElement) {
FieldElement element = findField();
String type = element.type?.getDisplayString();
assert(type != "dynamic");
//...
}
}
//...
}
I have stored variables in a class with their code names.
Suppose I want to get XVG from that class, I want to do
String getIconsURL(String symbol) {
var list = new URLsList();
//symbol = 'XVG'
return list.(symbol);
}
class URLsList{
var XVG = 'some url';
var BTC = 'some url';
}
Can someone help me achieve this or provide me with a better solution?
Dart when used in flutter doesn't support reflection.
If it's text that you want to have directly in your code for some reason, I'd advise using a text replace (using your favourite tool or using intellij's find + replace with regex) to change it into a map, i.e.
final Map<String, String> whee = {
'XVG': 'url 1',
'BTC': 'url 2',
};
Another alternative is saving it as a JSON file in your assets, and then loading it and reading it when the app opens, or even downloading it from a server on first run / when needed (in case the URLs need updating more often than you plan on updating the app). Hardcoding a bunch of data like that isn't necessarily always a good idea.
EDIT: how to use.
final Map<String, String> whee = .....
String getIconsURL(String symbol) {
//symbol = 'XVG'
return whee[symbol];
}
If you define it in a class make sure you set it to static as well so it doesn't make another each time the class is instantiated.
Also, if you want to iterate through them you have the option of using entries, keys, or values - see the Map Class documentation
I'd just implement a getProperty(String name) method or the [] operator like:
class URLsList{
var XVG = 'some url';
var BTC = 'some url';
String get operator [](String key) {
switch(key) {
case 'XVG': return XVG;
case 'BTC': return BTC;
}
}
}
String getIconsURL(String symbol) {
var list = new URLsList();
return list[symbol];
}
You can also use reflectable package that enables you to use reflection-like code by code generation.
Assuming that the class is being created from a JSON Object, you can always use objectName.toJSON() and then use the variable names are array indices to do your computations.
I currently created a new actionScript class, called Quiz.as
// package
// {
// public class Quiz
// {
public var knowledgePoints:int = 10;
public var allQuestions:Array = new Array;
public var questionCorrect:Boolean = false;
public function getTotalScore():int
{
// var totalScore:int = 0;
var totalScore = 0;
for (var i = 0; i < allQuestions.length; i++)
{
totalScore += allQuestions[i].getCalculatedScore();
if (currentModule.allQuestions[i].parent.questionCorrect)
{
knowledgePoints++;
}
else
{
knowledgePoints--;
}
}
debugLog("Total score: " + totalScore);
debugLog(knowledgePoints);
return totalScore;
}
// }
//}
This solution derived from my original question at: keeping track of a series of simple multiple choice web form answers
But now with the above code I am getting errors in flash console. My latest attempt to fix these errors are with the commented out regions above.
Error 1. Attribute used outside of class.
So I comment out first couple lines, but error continues to point to whatever line is exposed first.
Error 2. 'Int' could not be loaded.
Thanks for any advice,
Your issue is likely the result of using the above code on the timeline in AnimateCC/FlashPro.
Class files (and their corresponding attributes like public/private) need to be in their own actionscript (.as) file.
To create a class file in AnimateCC, go to file -> new and choose ActionScript 3.0 Class. Give it the class name of Quiz (so it matches what you've declared in your code)
Replace the default code with the class file code from your question (you'll need to restore those commented out lines too)
Save the file in the same directory as your .fla
To use your new class file in the timeline, you'd do something like this:
var quiz:Quiz = new Quiz(); //make an instance of your custom class
quiz.allQuestions.push(whateverAQuestionIs); //add a question to your array
trace(quiz.getTotalScore()); //trace out the total score
If you want to use that code in the timeline and forgo using a class file, you'll just need to remove the 4 public keywords (in addition to the lines you've already commented out)
I have two dart polymer components defined: an input and a list
This looks a little something like this:
#CustomTag('input-button')
class Input extends PolymerElement {
#observable String value = '';
Input.created() : super.created();
void blah(Event e, var detail, Node target) {
someMethodCallToTheOtherObject(value);
}
}
and the other element:
#CustomTag('page-content')
class PageContent extends PolymerElement {
final List<String> values = stuff;
PageContent.created() : super.created();
someMethodCallListerningForEventInOtherObject(String value) {
values.add(value);
}
}
As demonstrated in the code, I'm trying to set up and ActionListerner so that when one method is "fired" in the first button object, it calls a method in the second object with given parameters.
I know this might be a little of the basic side, but I haven't see this concept really well documented anywhere. Any input you could give to point me in the right direction would be appreciated.
Thanks!
You can query for one element and add an event listener
(querySelector(' /deep/ page-content') as PageContent)
.someMethodCallListerningForEventInOtherObject(value);
as PageContent is not necessary but it enables autocompletion.
You also need to import the file that contains the PageContent class to make this work.
or you can use an element like core-signals or a number of other possible variants depending on how your elements are organized (see my comments to your question).
I have a request to create a form filter that has two fields, one a freeform text
and the other a select. The value in the select will determine how to handle the value of the text is turned into a criteria.
I can create a custom addXXXColumnCriteria for either field, but how can I access the other field from within this function?
I suggest you not to use de addXXXColumnCriteria, but overwrite the FormFilter doBuildCriteria (Propel) or doBuildQuery(Doctrine) methods.
I have never used Propel, but I guess that works as good as for Doctrine.
For example:
class yourPropelFormFilter extends anyKindOfSfFormFilterPropel {
public function doBuildCriteria(array $values) {
$criteria = parent::doBuildCriteria($values);
// ... change the criteria behaviour with the $values array (do some print_r to $values to see how the data array is formatted)
return $criteria;
}
}
For Doctrine (remember to use the getRootAlias query method):
class yourDoctrineFormFilter extends anyKindOfSfFormFilterDoctrine {
public function doBuildQuery(array $values) {
$q = parent::doBuildQuery($values);
$rootAlias = $q->getRootAlias();
if(...) {
$q->innerJoin($rootAlias.'.RelationX rx')
->addWhere('rx.value = ?',$values['...']);
}
return $q;
}
}
Please, remember to return the criteria/query modified object!