Accessing Injected service in foreach - angular2 - dependency-injection

I have a component which has a service Injected into it's constructor and I have a map function on array of objects. When I tried access my model inside map function it's returning undefined error.
Code:
export class StrategyComponent implements ComponentDefinition{
type = "component";
strategies : any[];
constructor(#Inject(GateDataModel) private gateDataModel){
//Updatedcode
EmitterService.get("event_name")
.subscribe(obj => {
this.buildStrategies(obj.strategies);
})
}
buildStrategies(_strategies){
this.strategies = _strategies;
}
selectStrategy(i){ //Function called on click from template
this.gateDataModel.strategyId = this.strategies[i].id;
this.strategies.map(function(_strategy, index){
this.gateDataModel.strategyId = _strategy.id; //Error Here
i === index ? _strategy.isSelected = true : _strategy.isSelected = false;
})
}
}
How can I access my model inside map function?
Thanks

As I mentioned in the comment, I'm pretty sure the problem is calling 'this.gateDataModel.strategyId' inside the call back. this cannot be resolved in that scope. You have two options:
Trap this outside like so:
selectStrategy(i){ //Function called on click from template
this.gateDataModel.strategyId = this.strategies[i].id;
var _this = this;
this.strategies.map(function(_strategy, index){
_this.gateDataModel.strategyId = _strategy.id; //Error Here
i === index ? _strategy.isSelected = true : _strategy.isSelected = false;
})
}
You can use a function pointer arrow function expression instead:
selectStrategy(i){ //Function called on click from template
this.gateDataModel.strategyId = this.strategies[i].id;
this.strategies.map((_strategy, index) => {
this.gateDataModel.strategyId = _strategy.id; //Error Here
i === index ? _strategy.isSelected = true : _strategy.isSelected = false;
}) // You might need to check my syntax
}

Related

How to reset a ViewModel to default values

I have a object called Index:
function Index() {
var self = this;
self.name = ko.observable("Kiwanax");
}
And I have a ViewModel like this:
function IndexViewModel() {
var self = this;
var index = new Index();
self.content = index;
self.default = index;
}
ko.applyBindings(new IndexViewModel());
//-------------------------------------------
<input type="text" data-bind="text: content.name" />
The point is: in some point, I want to reset my form to default values. It means change the current viewmodel values to the default variable values. But I'm not figuring out how to do this.
self.resetForm = function() {
// How to update the current content variable to default variable values?
// I think in something like that below:
self.content = self.default;
}
Thanks all!
The form doesn't display anything because you should use the value binding with inputs.
As for the default values, my suggestion is to make an extender:
ko.extenders.defaultValue = function(target, option){
target.reset = function(){
target(option);
}
return target;
}
And use it like this:
self.name = ko.observable("Kiwanax").extend({defaultValue:"defaultValue"});
To reset to default call:
self.name.reset();
Fiddle with all code: http://jsfiddle.net/25ECB/3/
EDIT: To control a lot of fields, you could use ko mapping and use the create option to add the extender, but I prefer the implementation below, because it allows for an easy resetAll (updated fiddle: http://jsfiddle.net/25ECB/6/).
function Index() {
var self = this;
var lotsOfProps = [
{
name:"name1",
value:"initialValue1",
},
{
name:"name2",
value:"initialValue2",
},
{
name:"name3",
value:"initialValue3",
}
];
ko.utils.arrayForEach(lotsOfProps, function(prop){
self[prop.name] = ko.observable(prop.value).extend({defaultValue:prop.value});
});
//self.name = ko.observable("Kiwanax").extend({defaultValue:"defaultValue"});
self.resetAll = function(){
ko.utils.arrayForEach(lotsOfProps, function(prop){
self[prop.name].reset();
})
}
}
function IndexViewModel() {
var self = this;
var index = new Index();
self.content = index;
self.resetForm = function() {
// How to update the current content variable to default variable values?
// I think in something like that below:
self.content.resetAll();
}
}
Use a simple js object with default values:
function Index(data) {
var self = this;
self.name = ko.observable(data.name);
}
function IndexViewModel() {
var self = this;
self.defaultData = {name: "Kiwanax"};
self.index = new Index(defaultData);
self.resetForm = function() {
self.index = new Index(defaultData);
}
}
When you call resetForm, you just recreated Index object with default data.

Knockout array filter and Computed observable not working

i am new to Knockout. I am trying out a scenario and i am not able to make it work. please help. I am using MVC4.
function ViewModel(data) {
var self = this;
this.Collection = ko.observable(data);
self.GetFilteredCollection = ko.computed(function () {
var filteredCollection = ko.utils.arrayFilter(self.Collection(), function (item) {
return item.IsSelected == true;
});
return filteredCollection;
});
self.FilteredCollectionCount = ko.computed(function () {
return self.GetFilteredCollection().length;
});
});
var collectionList = eval('<%= new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model.Collection) %>');
var VM = new ViewModel(collectionList);
ko.applyBindings(VM);
I have binded the IsSelected property to checkbox. Initially the IsSelected property will be set to false.
<span id="Span1" data-bind="text:$root.FilteredCollectionCount"></span>
I am always getting the Span value as 0 even if i select the checkbox. But i could see the Property IsSelected changed to true.
You need to make the IsSelected into a observable for the computed observable to be able to be notified when the value of IsSelected has changed
If it already is a observable then you need to change the code to
return item.IsSelected() == true;

Check if textboxes have the same content

I want to check if the textboxes created like this:
(function(arr) {
for (var i = 0; i < arr.length; i++) {
app.add(app.createLabel(arr[i] + " mail"));
app.add(app.createTextBox().setName(arr[i]));
}
})(["first", "second", "third"]);
have the same contents? I was looking for something like getElementByTagname or or getTextboxes, but there are no such functions.
So how to iterate thvrough them and show a label if they are all equal?
To access any widget values you need to add them as a callback element (or a parent panel) to the server handler that will process them. The values of each widget are populated on a parameter passed to the handler function and can be referenced by the widget name (that you already set).
You don't need to setId as suggested on another answer. Unless you want to do something with the widget itself (and not its value). e.g. change its text or hide it, etc.
var textBoxes = ["first", "second", "third"];
function example() {
var app = UiApp.createApplication().setTitle('Test');
var panel = app.createVerticalPanel();
textBoxes.forEach(function(name){
panel.add(app.createLabel(name + " mail"));
panel.add(app.createTextBox().setName(name));
});
panel.add(app.createLabel('Example Label').setId('label').setVisible(false));
var handler = app.createServerHandler('btnHandler').addCallbackElement(panel);
panel.add(app.createButton('Click').addClickHandler(handler));
SpreadsheetApp.getActive().show(app.add(panel));
}
function btnHandler(e) {
var app = UiApp.getActiveApplication(),
allEqual = true;
for( var i = 1; i < textBoxes.length; ++i )
if( e.parameter[textBoxes[i-1]] !== e.parameter[textBoxes[i]] ) {
allEqual = false; break;
}
app.getElementById('label').setVisible(allEqual);
return app;
}
Notice that ServerHandlers do not run instantly, so it may take a few seconds for the label to show or hide after you click the button.
When you create the textboxes, assign each one an id using setId(id).
When you want to obtain their reference later, you can then use getElementById(id).
Here is an example:
function doGet() {
var app = UiApp.createApplication();
app.add(app.createTextBox().setId("tb1").setText("the original text"));
app.add(app.createButton().setText("Change textbox").addClickHandler(app.createServerHandler("myHandler")));
return app;
}
function myHandler() {
var app = UiApp.getActiveApplication();
app.getElementById("tb1").setText("new text: in handler");
return app;
}

AS2: Access class function from onRollOver

I am working on a class for building drop down buttons dynamically. Here is excerpt one of my code (located in the Class constructor):
_button.onRollOver = function()
{
this.gotoAndStop("over");
TweenLite.to(this.options,0.2 * optionCount,{_y:mask._y, ease:Strong.easeOut, onComplete:detectMouse, onCompleteParams:[button]});
function detectMouse(button:MovieClip)
{
button.options.onMouseMove = function()
{
for (var option:String in this._parent.children)
{
if (this._parent.children[option].hitTest(_root._xmouse, _root._ymouse, true))
{
if (!this._parent.children[option].active) {
this._parent.children[option].clear();
drawOption(this._parent.children[option], "hover");
this._parent.children[option].active = true;
}
}
}
};
}
};
I am attempting to call on the function drawOption() which is inside the same class and looks like so:
private function drawOption(option:MovieClip, state:String)
{
trace("yo");
switch (state)
{
case "hover" :
var backgroundColour:Number = _shadow;
var textColour:Number = 0xffffff;
break;
default :
var backgroundColour:Number = _background;
var textColour:Number = _shadow;
break;
}
option._x = edgePadding;
option._y = 1 + edgePadding + (optionPadding * (option.index)) + (optionHeight * option.index);
option.beginFill(backgroundColour,100);
option.lineStyle(1,_border,100,true);
option.moveTo(0,0);
option.lineTo(_optionWidth,0);
option.lineTo(_optionWidth,optionHeight);
option.lineTo(0,optionHeight);
option.endFill();
var textfield:TextField = option.createTextField("string", option.getNextHighestDepth(), 20, 2, _optionWidth, optionHeight);
var format:TextFormat = new TextFormat();
format.bold = true;
format.size = fontSize;
format.font = "Arial";
format.color = textColour;
textfield.text = option.string;
textfield.setTextFormat(format);
}
But because I am trying to call from inside an onRollOver it seems that it is unable to recognise the Class methods. How would I go about accessing the function without making a duplicate of it (very messy, do not want!).
In AS2 I prefer to use the Delegate class to add functions to event handlers whilst maintaining control over the scope.
You implement it like this:
import mx.utils.Delegate;
//create method allows you to set the active scope, and a handler function
_button.onRollOver = Delegate.create(this,rollOverHandler);
function rollOverHander() {
// since the scope has shifted you need to use
// the instance name of the button
_button.gotoAndStop("over");
TweenLite.to(_button.options,0.2 * optionCount,{_y:mask._y, ease:Strong.easeOut, onComplete:detectMouse, onCompleteParams:[button]});
}
everything in the onrollover relates to the button which is rolled over, to access the outer functions, you would have to navigate to the outer class before calling the function in exactly the same way that you are accessing the outer variables, eg:
if the parent of the button contains the function:
this._parent.drawOption(....)
ContainerMC class:
class ContainerMC extends MovieClip{
function ContainerMC() {
// constructor code
trace("Container => Constructor Called");
}
function Init(){
trace("Container => Init Called");
this["button_mc"].onRollOver = function(){
trace(this._parent.SayHello());
}
}
function SayHello():String{
trace("Container => SayHello Called");
return "Hellooooo World";
}
}
I then have a movieclip in the library with the Class ContainerMC and the identitfier Container_mc, which is added to the stage by this line in the main timeline:
var Container = attachMovie("Container_mc","Container_mc",_root.getNextHighestDepth());
Container.Init();
Edit: added working sample

SqlDataSource1_Selected not working

I need to be able to change a Boolean variable if a datasource actually retrieves any data, so gridviews/detailsviews aren't displayed. I've placed all the data inside a PlaceHolder tag which is by default not visible.
But using the SqlDataSource1_Selected method, it doesn't actually change the boolean variable - why is this? Here is my code:
protected void SqlDataSource1_Selected(object sender, SqlDataSourceStatusEventArgs e)
{
if (e.AffectedRows == 0)
{
displayData = false;
}
else
{
displayData = true;
}
}
And this is a snippet from my datasource in ASP to show it is indeed linking to the method:
onselected="SqlDataSource1_Selected"
I think you are going about this the wrong way
Can you try something like this
SqlDataSource DS = new SqlDataSource();
DataView DV = new DataView();
DS.ConnectionString = _Conn_String;
DS.SelectCommand = query_String;
DataView DV = new DataView();
DV = (DataView)DS.Select(DataSourceSelectArguments.Empty);
if (DV != null)
{
//display data
}
else
{
//do not display data
}

Resources