0

I'm using CakePHP 2.3.8 and I'm trying to call a function from within a knockout.js view model, but I'm having some trouble understanding what's going on.

If a specific variable is set (in PHP), then I want to display a div but I'm having trouble getting it to work. When I call it from the PHP code, the div doesn't display, however an alert message from within the method triggers so I know that code is being reached.

<div data-bind = "visible: someDiv">
    I'm visible
</div>

Here's the knockout viewmodel

function myViewModel(){

    var self = this;

    self.someDiv = ko.observable(false); //the div starts out hidden

    self.editing = ko.observable(false);

    //if the editing variable is changed, display someDiv
    self.editing.subscribe(function(){
        alert('edit changed'); //this alert triggers every time, even from the PHP call
        self.someDiv(true);  //someDiv only shows if I call from within the view model
    });

    //if I manually change editing to true from within the viewmodel, the div shows
    //self.editing(true);

}
ko.applyBindings(new myViewModel());

Here's the PHP code that initiates the sequence of events

echo $this->Html->script('knockout-2.3.0');
echo $this->Html->script('viewmodel');

//if the edit variable is set, the "someDiv" should be set to true
if(isset($edit)){
    <script>
        window.vm = new myViewModel();
        window.vm.editing(true); //this will trigger the alert from the subscribe function, but the div doesn't display
    </script>
}

Why is it when I change the editing value to true from PHP the div doesn't display, but if I change it from within the viewmodel it displays?

Is it even possible to do what I'm attempting?

Edit

I am applying bindings to my viewmodel in that JS file. I am not applying bindings again in the PHP file.

What I mean from "variable is set (in PHP)" is that the source of the data originates from PHP, although it is JavaScript setting the value in the end. I kept it short for my example above, so really it would be like this (not that it makes much of a difference)

//if the edit variable is set, the "someDiv" should be set to true
if(isset($edit)){
    <script>
        window.vm = new myViewModel();
        window.vm.editing(<?php echo $edit; ?>); //this will trigger the alert from the subscribe function, but the div doesn't display
        window.vm.another(<?php echo $something_else_here; ?>);
    </script>
}
user3476345
  • 331
  • 2
  • 6
  • 16

1 Answers1

1

Why is it when I change the editing value to true from PHP the div doesn't display, but if I change it from within the viewmodel it displays?

I don't see anywhere that you are setting it 'from php' it seems you are setting the value from JavaScript. If window.vm.editing(true); is firing the subscribe function then it is working successfully. The real question at that point is are you sure that you only have one instance of the VM that is being bound to the DOM? I don't see anywhere in your code where you are applying bindings at all so could you show that code as well?

I suspect your VM actually looks something like this -

function viewModel() {
    // some code
}

ko.applyBindings(new viewModel());

Or is being initialized twice. Remember that you need to reference the same instance of your view model.

window.vm = new myViewModel();
ko.applyBindings(window.vm);

//if the edit variable is set, the "someDiv" should be set to true
if(isset($edit)){
    <script>
        window.vm.editing(true); //this will trigger the alert from the subscribe function, but the div doesn't display
    </script>
}
PW Kad
  • 14,953
  • 7
  • 49
  • 82
  • I updated my original post to clear up the "set from PHP issue". Sorry about that. As far as being able to access the editing observable, how can I do that from outside of the viewmodel? – user3476345 Sep 26 '14 at 14:43
  • @user3476345 As mentioned the issue is that you are initializing your view model twice. As I mentioned before you call applyBindings in the JS set `window.vm = new myViewModel()` and then in your PHP or w/e you are trying to set the value just use `window.vm` and don't new another one up. – PW Kad Sep 26 '14 at 16:44