Github user doanduyhai commented on the pull request:
https://github.com/apache/incubator-zeppelin/pull/740#issuecomment-190404497
Hello @Leemoonsoo
> I think it's more clear to provide z.runParagraph() than z.angularBind()
has flag of runParagraph.
Having two different feature in a single function should be avoided.
The reason why I add the `runParagraph` option for `z.angularBind()` is
that it will be used in 80% of the time. Indeed, what's the point to bind an
Angular variable if you don't **refresh** immediately the target paragraph for
quick update ? I can't see any use-case where the user bind an Angular variable
and do not click on the "Run" button on the target paragraph(s) or on the whole
notebook itself.
If we remove the `runParagraph` option, to achieve the same feature, we'll
need:
```html
<input type="text" ng-click="z.angularBind(....); z.runParagraph(...)" >
```
or worst, the user should manually click on the target paragraph like in
the screenshot, it's far from being user-friendly.
> I think it can be improved by considering two perspective. The First one
is easy of use. User need to repeat paragraph id to series of z.angularBind()
again and again. e.g.
I do agree with your on this point to some extent. Yes, it forces the user
to do a manual copy and paste but once it's done, you don't need to update it
again (we'll see this point below).
But this issue also applies to `ZeppelinContext.runParagraph(String
paragraphId)` if we had chosen to use the ZeppelinContext to run paragraphs in
the back-end instead of front-end so I would say this issue is not really a new
issue, it has always been there.
> Second one is notebook portability, the code now depends on paragraph id
and it's not portable anymore. If you export notebook and import notebook, the
code will not work anymore unless user update all paragraph id in the code.
You are absolutely right about this point. Indeed it's vey annoying that
exporting and importing the same note make you loose the paragraph id. For this
I see 2 solutions:
1. first create the Angular `z` object from an HtmlElement as you suggest
`var z = getZeppelinContext(htmlElement)`, the only problem is what is
`htmlElement` ? How can we refer to a paragraph by its `htmlElement` ? I find
it simpler to refer to a paragraph using its **id**
2. **I think we should fix the dynamic paragraph id and persist the
paragraph id at the same time as the paragraph content**. As far as I can see,
the paragraph id is generated using some timestamp plus a random part so there
is very few chance of collision. Consequently it is possible to export a note
with all the original paragraph ids and import them elsewhere
WDYT ?
> front-end z.angularBind() call creates/updates angularObject into all
interpreters binded.
Allow me to disagree with this idea, if there are 10 paragraphs in the note
with 10 different interpreters, it will create a lot of **pollution**. There is
no reason that we push the Angular variable to many interpreters that are not
used by the target paragraph(s).
Another argument against binding the variable to all interpreters used by
the note is because Angular variables are **persisted** in `note.json` file so
we'll create a lot of data that will be exported/re-imported and not used ....
> Could you explain advantage of having API in both front-end and back-end
side ?
Yes, this is part of the goal **Usability Improvement** in the roadmap.
As an user, I want to be able to design a custom (with my own CSS etc ...)
HTML form with my own controls (input text, drop down, calendar component,
carrousel etc ...) and be able to push Angular variable to back-end.
Without this PR, to do this, I'll need to write Scala code like
```scala
import org.apache.zeppelin.display.angular.paragraphscope._
import AngularElem._
<div>
<div class="alert alert-info">This is an alert panel</div>
<form class="form-inline">
<div class="form-group">
<input type="text" class="form-control" placeholder="Input
Text"></input>
</div>
<button type="submit" class="btn btn-primary">Click Me</button>
</form>
</div>.onEvent("ng-click", () => {
//my callback routine
}).display
```
If I were a web developer using Zeppelin, **I don't understand why I am
forced to use Scala and the Spark interpreter to produce AngularJS and HTML
source code**...
Isn't it more natural to write **plain Javascript and AngularJS code** if
you want to render HTML and bind AngularJS ?
I have given many talks about Zeppelin since 6 months and everytime I
build a beautiful pure HTML form using Bootstrap, people in the audience ask me
why I have another paragraph with source code like this:
```scala
z.angularBind(...)
z.runParagraph(...)
```
It seems so un-natural for users to have Scala code in a separate
paragraph just to make the HTML form work. If we want to extend the user-base
of Zeppelin, we need to provide user natural ways of creating Angular variable
and not force them to use the Spark interpreter for that.
There is also a demande on the user-mailing list recently to be able to
update Angular variable from the front-end:

So the demand for controlling Angular element is real, not just some fancy
idea I have in mind.
> Cons side, if user creates something that mixes both front-end side API
and back-end side API at the same time, while front-end side(js in webbrowser)
and back-end side (heterogeneous interpreters) runs asynchronously, i can
easily imagine understanding behavior of those code will be really difficult.
Totally agree that if one user try to bind AngularJS using the back-end
API with ZeppelinContext or the new Angular API you introduce and the front-end
API I propose, it will make things complicated. But again, it's the user
responsibility to make clean code. You can never stop people from doing stupid
things right ?
To conclude, what I propose is to make another PR, before we progress on
this one, **to persist the paragraph Id with the note content** so that we
don't have anymore export/import problem.
WDYT ?
---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at [email protected] or file a JIRA ticket
with INFRA.
---