Search code examples
python-3.xangularjsdata-bindingbindingapache-zeppelin

Apache Zeppelin python to angular binding does not happen all the time, unbinding gives error


I have created an angular download button with countdown timer as part of a larger Apache Zeppelin notebook (url below is changed for this example). Once the countdown completes, the button is disabled. I am binding python variables via z.angularBind() so my angular paragraph can use them. This seems to be inline with the back-end API calls. However, sometimes (and inconsistently) the bindings do not successfully occur, and so the button doesn't display because timer does not exist. I have verified this by displaying the bound values below the button, and they are empty, but only sometimes.

Here are my three sequential zeppelin notebook paragraphs:

%python
# z.angularUnbind("url")
bunny = 'https://positively.com/files/bunny-on-side.jpg'
z.angularBind("url", bunny)
%angular
<div>
    <a ng-if="timer>=0" ng-href="{{ url }}" class="btn btn-primary">Download a bunny image</a>
    <a ng-if="timer<0" ng-href="{{ url }}" class="btn btn-primary" disabled>Button Expired</a>
    <br>
    <em>Countdown: {{ timer }}</em>
</div>
<br>
Variables: {{ timer }}, {{ url }}
%python
import time
counter = 10
while counter >= 0:
    z.angularBind("timer", counter)
    time.sleep(1)
    counter -= 1
z.angularBind("timer", counter)

The issue can occur on sequential re-runs of the same notebook, when I re-open the notebook, or importing and then running for the first time. The image below is what the issue looks like in Zeppelin after being run. Any suggestions are appreciated, thanks!

unbound angular variable result

This is what it should look like all the time when running correctly:

correct angular binding

Followed by:

expired button

I attempted to z.angularUnbind() my variables at the start of the first python paragraph in case variables were conflicting somewhere (commented out), but got the following error which almost seems like angularUnbind() is expecting the front-end API, leaving me especially confused. Putting a paragraph id as the second argument didn't resolve the error message.

Py4JError: An error occurred while calling o0.angularUnbind. Trace:
py4j.Py4JException: Method angularUnbind([class java.lang.String, class java.lang.String]) does not exist
    at py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:318)
    at py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:326)
    at py4j.Gateway.invoke(Gateway.java:274)
    at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132)
    at py4j.commands.CallCommand.execute(CallCommand.java:79)
    at py4j.GatewayConnection.run(GatewayConnection.java:238)
    at java.lang.Thread.run(Thread.java:748)

Solution

  • %python
    z.z.angularUnbind("url")
    bunny = 'https://positively.com/files/bunny-on-side.jpg'
    z.z.angularBind("url", bunny)
    

    it should work, make above changes to the python code.

    Through ZeppelinContext, you can bind / unbind variables to AngularJS view. Currently, it only works in Spark Interpreter ( scala ).