Is it possible to add all content items of a specified content type to a list without having to do it one by one? (there are a lot of items!)
The answer is in this code fragment, but that leads to another question.
Here is the code:
#{
var allConsultants = CreateSource<EntityTypeFilter>();
allConsultants.TypeName = "Consultant";
var consultantsList = AsDynamic(#allConsultants.List);
}
#functions{
public static string GetTitle(ToSic.SexyContent.DynamicEntity theConsultant)
{
return theConsultant.FirstName + theConsultant.LastName;
}
}
Consultants List: #consultantsList<br/><br/>
#foreach(var cont in consultantsList ){
<div class="sc-element">
#cont.FirstName #cont.LastName #GetTitle( cont )
</div>
}
Now my question:
I want to pass each item in the list (variable cont) to a function that examines the items fields and then returns a string. Here, I just want to grab the first and last names and concatenate them.
But, while I can pass in the item cont as a ToSic.SexyContent.DynamicEntity, that seems not to pass in the structure, so I cannot access the fields as in .LastName.
So, how do I do this?
Thanks.
And
public static string GetTitle(T dynamic theConsultant)
does the trick!
Related
I have a computed array which is full of tags and updates depending on what selection i make in the select box. I would like to take this array and pass it to a method and then run a method to update what “results” have an active class. Although I get an array saying I can’t run forEach on this element.
Been through a few topics and understand computed properties dont work like that but surely there is a way around this.
https://jsfiddle.net/39jb3fzw/6/
Short Snippet
methods: {
updateOutput() {
var tags = this.tagArray;
tags.forEach(function(tag) {
console.log(tag);
})
}
},
computed: {
concatenated: function () {
var ret = this.selected.concat(this.selected2, this.selected3);
this.tagArray = ret;
//this.updateOutput();
return ret;
}
}
Full Output
https://jsfiddle.net/39jb3fzw/6/
Thanks again :slight_smile:
It looks like the issue is the line:
var ret = this.selected.concat(this.selected2, this.selected3);
That line of code is returning an empty string rather than an array. This is because this.selectedX is a string rather than an Array. This explains why tag.forEach is undefined. forEach doesn't exist on the String prototype.
You can create this an array instead be doing
var ret = [ this.selected, this.selected2, this.selected3 ]
From there you can set this.tagArray to ret
Hope this helps
I have many class in my library almost 300, and I want to generate instance name by loop. In other words I wanna instead of this approach(witch has many code line):
X:This is my problem:
var cm1: Cm1 = new Cm1();
var cm2: Cm2 = new Cm2();
var cm3: Cm3 = new Cm3();
...
use like this approach (less than 10 code lines):
Y:I think this is solution:
for (var i: uint = 1; i < 4; i++)
{
var getChildByName("cm" + i): getChildByName("Cm" + i) = new getChildByName("Cm" + i);
}
but I know above code does not work, is there any way to make them !
-What am I actually trying to solve?
Make many variable by a few line code and save time and size app!
-Why do I have ~300 classes and why are you trying to create them in a loop at once?
This is about to data of request application!
-What do these classes do that you unconditionally need one of each all at the same time?
Because those data would show at first time!
First, it is better to store the classes in an Array or Object rather than an external variable for each item. if you want to access them by name, better to use object:
var classList:Object=new Object();
Then in your loop:
for(var i:uint=1;i<NumberOfClasses;i++){
classList["cm"+i.toString()]=new (getDefinitionByName("Cm"+i.toString()) as Class)();
}
getDefinitionByName is used to make Constructors using String;
Note: if your classes contain a package directory, you should include it. for example:
getDefinitionByName("myclasses.cm.Cm123")();
Then you can access them using Bracket syntax:
classList["cm123"].prop=val;
And don't forget to:
import flash.utils.getDefinitionByName;
I Hope it will help.
EDIT
to use Array instead of object, the loop should be:
for(var i:uint=1;i<NumberOfClasses;i++){
classList[i]=new (getDefinitionByName("Cm"+i.toString()) as Class)();
}
then to access them:
addChild(classList[0]);//0 or any other index;
Alright, so I got a private ?Vector $lines which is empty when constructing the object and now I want to add strings to that Vector. The following Hack code works well:
<?hh
class LineList {
private ?Vector<string> $lines;
public function addLine(string $line): void {
$this->file[] = trim($line);
}
}
But when checking the code with hh_client, it gives me the following warning:
$this->file[]]: a nullable type does not allow array append (Typing[4006])
[private ?Vector<string> $lines]: You might want to check this out
Question: How do I add elements to the Vector without that the checker pushs this warning?
The easiest way would be to not use a nullable Vector. private Vector<string> $lines = Vector {}; gets around the need for a constructor too.
Otherwise, you'll need to check if the value isn't null, then append to it:
public function addLine(string $line): void {
$vec = $this->lines;
if ($vec !== null) $vec[] = trim($line);
}
You can't just check if $this->lines !== null as it is possible for it to change value between checking and appending (with something like a tick function), hence why it is assigned to a local variable instead.
Let's say I have an array, each item in the array has a corresponding library item.
I'd like to do something like :
var rando = Math.round(Math.random()*3)
var myArray = new Array ["ball", "wall", "fall"]
var i:myArray[rando] = myArray[rando] new myArray[rando]()
addChild(i)
But, this doesn't work. What's the secret?
Thank You,
Victor Hugo
Surprised no one mentioned getDefinitionByName() here.
Here's some complete code to get your example working:
var myArray = ["ball", "wall", "fall"];
/**
* Creates a random instance based on an input array containing class names as Strings.
* #param The input array containing aforementioned Strings.
* #return The newly created instance.
*/
function createRandom(typeArray:Array):*
{
// Select random String from typeArray.
var selection:String = typeArray[ int(Math.random() * typeArray.length) ];
// Create instance of relevant class.
var Type:Class = getDefinitionByName(selection) as Class;
// Return created instance.
return new Type();
}
// Randomly create and add instance.
var instance:DisplayObject = createRandom(myArray);
addChild(instance);
Ok so there are a bunch of problems with this.
A large one being var i:myArray[rando] = myArray[rando] new myArray[rando]() not really too sure what you're trying to do here.
Anyway I'm going to assume ball, wall and fall are instance names of MovieClips you have in your library. I think you're going to want something like this
var rando:int = Math.floor(Math.random()*3); //As the comments point out this should give you a random
//int between 0 and 2, arrays are 0 indexed so this is what we want if we have 3 items
Now for your array, you're current putting strings in there. Flash has no idea what "ball", etc are.
Try something like this
var myArray:Array = new Array [new ball(), new wall(), new fall()]; //this creates a new instance of your library object and stores it in your array
Now to add one of these to your stage:
addChild(myArray[rando]); //this uses the random number to pull one of the items out of your array
What you're trying to do with var i:myArray[rando] doesn't really make sense. There is no type of myArray[rando] this slot should be holding a MovieClip
If you only have a few choices, it's easier to use a switch-case.
switch (rando) {
case 0:
i = new ball();
break;
case 1:
i = new wall();
break;
case 2:
i = new fall();
break;
}
addChild(i);
I suggest you define the variable i as a MovieClip, in which case it can be instantiated as both ball, wall, fall.
Given that ball, wall and fall are in the library exported to actionscript.
Just guessing off your limited information but give this a shot.
private function myFunction():void{
var rando = Math.round(Math.random()*3);
var myArray= new Array ["ball", "wall", "fall"];
}
private function generateItem(item:String):void{
switch(item){
case "ball" : generateBall(); break;
case "wall" : generateWall(); break;
case "fall" : generateFall(); break;
}
private function generateBall():void{
//code to generate ball
addChild(ball);
}
private function generateFall():void{
//code to generate fall
addChild(fall);
}
private function generateWall():void{
//code to generate wall
addChild(wall);
}
Change your arrary line to:
var myArray = new Array [ball, wall, fall];
This should work. :)
Marty Wallace gets big praise for steering me down the path of getDefinitionByName(). The example he posted was good, but this example does exactly what I was going for.
http://www.emanueleferonato.com/2011/03/31/understanding-as3-getdefinitionbyname-for-all-eval-maniacs/
Here's what I'm currently doing/trying to do to accomplish my goal. But it is not removing the "row" the way I would like it too.
So, I'm making an object, then pushing it into an array. And the adding to the array part works fine and just as I expect.
var nearProfileInfoObj:Object = new Object();
nearProfileInfoObj.type = "userInfo";
nearProfileInfoObj.dowhat = "add";
nearProfileInfoObj.userid = netConnection.nearID;
nearProfileInfoObj.username = username_input_txt.text;
nearProfileInfoObj.sex = sex_input_txt.selectedItem.toString();
nearProfileInfoObj.age = age_input_txt.selectedItem;
nearProfileInfoObj.location = location_input_txt.text;
nearProfileInfoObj.headline = headline_input_txt.text;
theArray.push(nearProfileInfoObj);
So after that later on I need to be able to remove that object from the array, and it's not working the way I'm expecting. I want to take a variable whoLeft and capture their ID and then look in the array for that particular ID in the userid part of the object and if its there DELETE that whole "row".
I know you can do a filter with an array collection but that doesnt actually delete it. I need to delete it because I may be adding the same value again later on.
whoLeft = theiruserIDVariable;
theArray.filter(userLeaving);
public function userLeaving(element:*, index:int, arr:Array):Boolean
{
if (element.userid == whoLeft)
{
return false;
}
else
{
return true;
}
}
But this doesnt seem to be deleting the whole row like it implies. Does anyone know what i'm doing wrong?
Instead of modifying the original array, the new filtered array is returned by the filter method. So you need to assign the returned array to theArray.
Try this
theArray = theArray.filter(userLeaving);
EDIT This turned out to be slower than for loop:
An alternative to the hand coded loop could be something like this:
theArray.every(searchAndDestroy);
public function searchAndDestroy(element:*, index:int, arr:Array):Boolean
{
if (element.userid == whoLeft)
{
arr.splice(index,1);
return false;
}
return true;
}
As far as I know, every() terminates the first time the test function returns false. So the question is: for a big list, which is faster, the for loop or the loop that every() does with the overhead of the test function call.
EDIT #2 But this was faster than a for loop for a test I ran on an array of a million Points:
for each(var element:Object in theArray)
{
if (element.userid==whoLeft)
{
theArray.splice(theArray.indexOf(element),1);
break;
}
}
I think this is what you're looking for:
for(var i:uint = 0, len:uint = theArray.length; i<len; i++)
{
if(thisArray[i].id == whoLeft.id)
{
thisArray.splice(i, 1);
break;
}
}
However, do you really need it in an Array because you could always use a Dictionary which would mean accessing it by id which would be a lot simpler to remove.