KnockoutJS - How to reassign URL when checkbox is checked vs. unchecked - asp.net

I want to assign an URL in a function everytime a checkbox is checked. But I would also like the URL to be reassigned its initial value when the checkBox is unchecked. I was able to create the code below from the following thread, but the URL is not reassigned when I uncheck the box. Sorry I am new to KnockoutJS and to JavaScript in general.
HTML
<input type="checkbox" name="myCheckBox" data-bind="checked:isChecked, click: setUrl">Search Supplier<br>
JS
searchShippingCodesUrl = '/Parteners/Search';
...
...
ischecked: ko.observable(false),
setUrl: function () {
searchShippingCodesUrl = '/Suppliers/Search';
return true;
},
Thank you for your time.

Only use the click binding on a checkbox if you need to differentiate whether the checkbox changed state by click vs. by internal setting. The checked binding captures the state of the view for you, so you can then work with it in your viewmodel. To take action when it changes, you subscribe to the observable (I borrow the variables here from dfperry's example):
ischecked.subscribe(function (newValue) {
searchShippingCodesUrl = newValue ? supplierSearch : partnerSearch;
});

You need to check against isChecked in your setUrl function to get that toggle effect:
var partnerSearch = '/Partners/Search',
supplierSearch = '/Suppliers/Search';
searchShippingCodesUrl = partnerSearch;
...
ischecked: ko.observable(false),
setUrl: function () {
searchShippingCodesUrl = (ischecked() ? supplierSearch : partnerSearch);
return true;
}

Related

Can a Meteor method call get invoked via Collection.findOne

In my Meteor code. Can I define a method "or a function" on the server and call it on collectionName.findOne({id: 'someId'}).methodName; on the client?
Being new to Meteor, I don't know if this is possible and if so, what would the syntax look like? Thanks
This code is just a brain dump.
//server
Meteor.method({
doWork1: function (args) {
//do work
return something;
}
});
MyCol = new Mongo.Collection('myCol');
MyCol.insert({item: "envelopes", qty : 100, myFunc: doWork1});
//client
Meteor.call(MyCol.findOne({item: 'envelops'}).myFunc;
Edited:
Blaze Sahlzen comments made me think and add the following.
The reasons why I thought to give a mongo collection a try is this:
Stage one: the user fills up a form and click a button, the input values need to be used as arguments for a method which when successfully returns, the form gets modified to show different input fields for the user to fill up again and click the SAME button.
Stage two: same as stage one but with different input fields again.
Stage n: same as stage n-1 but with different input fields again.
I need to store all input values and group them by their stage identifier.
Each method may add/remove different kind of input controls for the next stage.
Since the SAME button will be used thus I don't have different buttons for different methods, so I came up with my original question "brain dump code". You are welcome to reinvent or change it and offer yours. :) Thanks again.
edited 2
A practical example could look like this:
var stageOne = {};
//for each DOM input
stageOne[inputName][i]= [inputValue][i];
myCol.insert({'stageOne': stageOne});
//then an observer for stageOne
But I just can't get my head around how to "link" each stage with the correct method to call without having to use a long if or switch conditional statement.
Alright, if I understand what you mean, I don't think you need observeChanges. The following solution might be a bit extensive, so bear with me.
Firstly you need a session variable to control on the client side which form values need to be shown. You could introduce this variable in your Template.name.onRendered.
Session.set('stage',1);
Then you have your input fields
<form>
<label id="label1">{{label1}}</label>
<input id="field1" type="text"/>
<label id="label1">{{label2}}</label>
<input id="field2" type="text"/>
<label id="label1">{{label3}}</label>
<input id="field3" type="text"/>
<button id="form-submit" type="submit"/>
</form>
I can imagine that you want to switch up the names of their labels to reflect the change in forms as you go to different stages. As a result you can write helpers as such:
'label1': function(){
var myStage = Session.get('stage');
if (myStage == 1){return '<label-title-for-stage-1>';
} else if (myStage == 2){return '<label-title-for-stage-2>';}
} else if .... etc.
}
Any changes to the session variable 'stage' will force the helper to reload, making it ideal to update form titles as you go through your stages.
You can then write an event for the button click event as such:
'submit #form-submit': function(){
var options = {
stage: Session.get('stage'),
values: [
{ value: $('#field1').val(), name:$("#label1").text() },
{ value: $('#field2').val(), name:$("#label1").text() },
{ value: $('#field3').val(), name:$("#label3").text() }]
}
Meteor.call('storeValues', options, function(error, result) {
if (error) {
console.log(error);
}
Session.set('stage',result);
});
}
This will essentially combine the filled fields into one object and call upon a server method, waiting for a callback from the server that tells the client which stage to move to.
Now, on the server side you can insert the values for this particular user in your collection and see if a particular stage has filled up and return whether the client can move on to the next stage.
Meteor.methods({
'storeValues': function(options){
for (var i = 0; i < options.values.length; i++){
myCol.insert({
value:options.values[i].value,
name:options.values[i].name,
stage: options.stage
});
}
if (options.values.length > 'amount-per-stage'){
return options.stage + 1;
} else {
return options.stage;
}
}
});
This way you store the data that gets entered in each form, while moving up one stage each time if all fields have been entered.
What you could do is use observeChanges:
var query = MyCol.find({item: 'envelops'});
var handle = query.observeChanges({
added: function () {
somethingHappened();
},
changed: function () {
somethingHappened();
}
});
var somethingHappened = function(){
// do something
}
Query contains your collection, and the handle function automatically checks whether any changes are being made to that collection, triggering the somethingHappened function if there are.
Inside somethingHappened you can place the behaviour that you would normally place in your method.
You can use observeChanges both client side and server side, but in this case you only need it on the server side.

How to Stop the binding when the controls are initializing in the DOM

I'm having a question about knockout binding to a select list. the problem is if we attached a click binding to a control, the event will be executed whenever the control is clicked. but why this select change event is firing while the control is loading to the DOM. I'm using knockout for last three week. this is the fiddle for that.
http://jsfiddle.net/aroor/dUvRx/4/
<select data-bind='options :list, optionsText: "name", value:selectedItem , event : { change : onSelectChange }'></select>
var model = function(){
var self = this;
self.name = ko.observable();
self.key = ko.observable();
self.visible = ko.observable();
self.selectedItem = ko.observable();
self.onSelectChange = function(data,event){
var currentSelection = self.selectedItem();
if(currentSelection.visible )
{
// display the content according to the selection
}
}
};
ko.applyBindings(new model());
please help me to sort this problem.
I don't want to use the optionsCaption to select the default item. because the collection is coming from a ajax call.
Your onSelectChange method is based off of the values of the select box. Thus, when the value changes as a result of the data binding (such as when the items are first added to the list), it is correct for this event to fire.
Instead of basing your change event off of the select box, it might be better to base your change event off of the data-bound properties.
First, you could change your list to be an observable array.
list = ko.observableArray([{ name : "test-01", key : 1, visible: true},
{ name : "test-02", key : 2 , visible: false},
{ name : "test-03", key : 3 , visible: false},
{ name : "test-04", key : 4 , visible: true}
]);
selectedItem = ko.observable();
In your markup:
<select data-bind='options :list, optionsText: "name", value:selectedItem'></select>
Now, whenever you want to determine if the item has changed, you can use the ko.subscribe function.
selectedItem.subscribe(function(newValue) { /* Do stuff when the value changes here */ });

ObservableArray not notifying when item changed

I try to bind observableArray to div on my page and everything is ok. This array contains simple JSON objects, not observable, obtained from WebService.
After that, I want to be able to modify those objects in array and would like view to be refreshed with each modification. For example, when checkbox gets clicked I would like to change the flag on my JSON object (this seems to work automatically all right) and at the same time my UI should get updated, which does not happen. Could anyone provide me with the reason (is this because those objects are simple, not observable?) and solution?
var DocumentContentModel = function () {
var self = this;
self.content = ko.observableArray();
self.ElementApprovalChanged = function (element) {
DocumentService.DoSomething(
element.Id,
function (result) {
if (!result) {
var negatedApproved = !element.Approved;
element.Approved = negatedApproved;
}
},
function (error) {
alert(error);
});
return true;
};
};
$(document).ready(function () {
var contentModel = new ContentModel();
DocumentService.GetContent(1,
function (result) {
contentModel.content(JSON.parse(result));
});
ko.applyBindings(contentModel);
});
UI
<div class="ContentContainer">
<div data-bind='foreach: content'>
<div class="ContentElement" data-bind='css: { NotApproved: !Approved} '>
<div class="ContentValue" data-bind='html: Value'></div>
<div class="Approval">
<input type="checkbox" data-bind='checked: Approved, click: $root.ElementApprovalChanged' />
</div>
</div>
</div>
</div>
What is happening is on checkbox click I send request to webservice and if this call returns false I want to reset element's Approved flag. And even whithout that, selecting checkbox should change div class attribute to mark it as NotApproved when needed. But none of this happens.
An observableArray only tracks the array. So if something is added, removed or replaced in the array this will trigger an update to your view.
An observableArray does NOT track the state of individual properties on the items in the array. So if you have an Approved flag on your objects this needs to be an observable for the UI to reflect changes to that property.
So you would have something like:
element.Approved = ko.observable(false);
....
....
if (!result) {
var negatedApproved = !element.Approved();
element.Approved(negatedApproved);
}
(or if you want to be more consise:
element.Approved(!element.Approved());
)

Use actionscript to uncheck a checkbox in a component?

I have a component with checkboxes, the checkboxes are bound to booleans in the main code:
<mx:CheckBox id="LyrClearAll" selected="{Application.application.bLyrClearAll}"/>
This works fine for the checkboxes that don’t change unless a user interacts with them again. My problem appears because I want to “uncheck” one of the boxes everytime the component is closed. (I know something other than a checkbox would work better, but I’m trying to keep things consistent in this component.)
I have tried setting the bound Boolean variable to false, and I’ve tried setting the checkbox.selected value to false. Neither are working, everytime I open the component the checkbox is still checked.
private function makeLyrsPopUp(evt:MouseEvent):void
{
var panelLyr:popUpLayers = PopUpManager.createPopUp(this, popUpLayers, false) as popUpLayers;
panelLyr.LyrClearAll.selected == false; //?? set checkbox back to unchecked
panelLyr["cancelButton"].addEventListener("click", removeMe);
panelLyr["okButton"].addEventListener("click", submitData);
PopUpManager.centerPopUp(panelLyr);
function submitData(event:Event):void //change layer visibility based on check boxes in popupLayer
{
bLyrStreet = panelLyr.LyrStreet.selected;
bLyrParcel = panelLyr.LyrParcel.selected;
bLyrClearAll = panelLyr.LyrClearAll.selected;
if (bLyrClearAll)
{
clearLayers();
bLyrClearAll == false; //?? set checkbox back to unchecked
}
removeMe(event);
}
}
Needed to change == false to = false
bLyrClearAll should be declared bindable:
[Bindable]
var bLyrClearAll: Boolean;

Calling my own function during with onClick

How do I call a user-define function such as this one using the onClick attribute of a input button? More specifically what special steps must I take in JQuery and what would the HTML markup look like? Thanks
function simClick(keyCode) {
var e = jQuery.Event("keypress");
e.keyCode = 8;
$(document).trigger(e);
}
<input type="button" ID="delBtn" class="calcBtn" value="Del" onclick="???????" />
HTML
<input type="button" ID="delBtn" class="calcBtn" value="Del" />
Javascript in separate file
// When the DOM is ready
$(function() {
// Function that is executed w keypress or button click
doThis = function() {
// Stuff to do
}
// To do when element with ID delBtn is clicked
$("#delBtn").click(function() {
// Stuff to do when input is clicked
doThis();
});
// To do when key is pressed
$(document).keydown(function(event) {
// Stuff to do when key is pressed
// Can check which key was pressed here.
var code = (event.keyCode ? event.keyCode : event.which);
if(code == 8) { //Enter keycode
doThis();
}
});
});
There are many ways to attach a handler to when that button is clicked. Take a look at jQuery selectors.
You could also use the attribute equals selector
$("input[value='Del']")...... // For the input with a value of Del
I'm not sure what you quoted JS has to do with the input button, since it looks like you're trying to work with a keypress instead of a click in that function.... But the above jQuery is how you capture a click on that input button.
Take a look at, "Which key was pressed?"

Resources