├── .gitignore
├── LICENSE
├── README.md
├── compile_readme_preview.bat
├── img
├── demo.png
└── jasmine.png
├── pom.xml
├── vaangular-demo
├── VaangularApplication.launch
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── de
│ │ │ └── akquinet
│ │ │ └── engineering
│ │ │ └── vaadin
│ │ │ └── vaangular
│ │ │ └── demo
│ │ │ ├── VaangularApplication.java
│ │ │ ├── VaangularServlet.java
│ │ │ ├── VaangularUI.java
│ │ │ └── weather
│ │ │ └── Weather.java
│ └── resources
│ │ ├── application.properties
│ │ └── de
│ │ └── akquinet
│ │ └── engineering
│ │ └── vaadin
│ │ └── vaangular
│ │ └── demo
│ │ └── weather
│ │ ├── weather.html
│ │ └── weather.js
│ └── test
│ └── resources
│ └── de
│ └── akquinet
│ └── engineering
│ └── vaadin
│ └── vaangular
│ └── demo
│ └── weathertest
│ ├── weatherSpec.js
│ └── weatherTest.html
└── vaangular
├── assembly
├── MANIFEST.MF
└── assembly.xml
├── pom.xml
└── src
├── main
├── java
│ └── de
│ │ └── akquinet
│ │ └── engineering
│ │ └── vaadin
│ │ └── vaangular
│ │ └── angular
│ │ ├── MethodInvoker.java
│ │ ├── NgTemplate.java
│ │ ├── NgTemplatePlus.java
│ │ ├── NgTemplateState.java
│ │ └── ServiceMethod.java
└── resources
│ └── de
│ └── akquinet
│ └── engineering
│ └── vaadin
│ └── vaangular
│ └── angular
│ └── NgTemplate.js
└── test
├── java
└── de
│ └── akquinet
│ └── engineering
│ └── vaadin
│ └── vaangular
│ └── angular
│ ├── MethodInvokerTest.java
│ ├── NgTemplatePlusTest.java
│ └── NgTemplateTest.java
└── resources
└── de
└── akquinet
└── engineering
└── vaadin
└── vaangular
└── angular
└── angular.html
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 | # Mobile Tools for Java (J2ME)
4 | .mtj.tmp/
5 |
6 | # Package Files #
7 | *.jar
8 | *.war
9 | *.ear
10 |
11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
12 | hs_err_pid*
13 |
14 | # Eclipse
15 | .project
16 | .classpath
17 | .settings
18 | target
19 |
20 | README.html
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | vaangular
2 | =========
3 |
4 | Provide stellar integration of AngularJS with vaadin.
5 |
6 | ## What is vaangular?
7 | vaangular combines the power of [vaadin](https://vaadin.com) and Java with the power of [AngularJS](https://angularjs.org) to create awesome UIs.
8 |
9 | Some reasons why you might want to do that:
10 | - mix and match skill within your team
11 | - increase responsiveness (by doing client-side logic)
12 | - re-use existing AngularJS-based assets
13 | - have an alternative to custom GWT development
14 |
15 | you don't have to do any GWT development. Check out all necessary steps below.
16 |
17 | ## How does it work? (examples, please!)
18 |
19 | Effectively, you create three things:
20 | 1. an HTML fragment with AngularJS attributes and directives in it
21 | 2. an AngularJS controller (along with tests in e.g. Jasmine)
22 | 3. a vaadin component to hook up the previous two with the backend
23 |
24 | vaangular makes extensive use `com.vaadin.ui.AbstractJavaScriptComponent` and adds additional logic to bridge vaadin *states* with AngularJS *$scope(s)*. If you want, you can combine the [JavaScriptPlus for vaadin](https://github.com/akquinet/JavascriptPlusForvaadin) add-on with this add-on to use deferred variable changes in AngularJS.
25 |
26 | A comprehensive demo is included that shows the full roundtrip (see the `vaangular-demo` folder for all the code - you can fire off this example by running `de.akquinet.engineering.vaadin.vaangular.demo.VaangularApplication.main` which invokes Spring Boot, pulls up a server and offers you an endpoint at `localhost:8090`)
27 |
28 | We'll use this as an example throughout the page... (it's best viewed in Webkit = Chrome / Safari btw.)
29 |
30 | Here's what the example looks like:
31 |
32 |
33 |
34 | En detail: the current weather (1) is displayed depending on the slider position (2) - this happens without server roundtrips (pure AngularJS). When clicking a 100%-vaadin-like AngularJS-button (3) or a standard-vaadin-button (4), you get a popup window (5) - this happens in vaadin (so there is a seamless integration between those two).
35 |
36 | ## Running the example from source
37 |
38 | You can run the example via
39 |
40 | ```
41 | mvn exec:java -Dexec.mainClass="de.akquinet.engineering.vaadin.vaangular.demo.VaangularApplication"
42 | ```
43 | from ```vaangular-demo```
44 |
45 | ## Creating a component
46 |
47 | ### Project structure
48 |
49 | We recommend using [Maven](http://maven.apache.org) as build tool - which results into src/main/java, src/main/resources, etc. as base directory structure along with a pom.xml
50 |
51 | Furthermore, you can utilize Spring Boot, Eclipse, etc. (what our example does)
52 |
53 | ### Creating the package
54 |
55 | Create a package (with identical names) in both src/main/java and src/main/resources - in our example: `de.akquinet.engineering.vaadin.vaangular.demo.weather`
56 |
57 | ### Creating the HTML fragment
58 |
59 | Create an HTML file with the same name as the last part of the package (here: 'weather') ending with '.html'. The file can contain any markup as long as there is exactly one topmost tag.
60 |
61 | So, your 'weather.html' can initially look like this:
62 | ```html
63 |
64 |
65 |
66 |
67 |
68 |
{{zeit}}
:00
69 |
70 |
71 |
72 |
73 |
74 | {{userState.buttonCaption}}
75 |
76 |
77 |
78 | ```
79 |
80 | What it does is:
81 | - declare a div to take up some dynamic values (rendered by *content()*)
82 | - create a range input field
83 | - create some labels below (yes, inline styling is bad, but verbose examples are, too)
84 | - provide a button in AngularJS that looks exactly like a button in vaadin
85 |
86 | ### Creating the AngularJS controller
87 |
88 | Obviously, our file also needs a controller which mainly needs to do two things:
89 | - render the content based on where the slider is (we use inline HTML via ngSanitize)
90 | - move the slider upon label click
91 | - make the slider pos available to vaadin (we use deferred variable changes via `setDeferredVariable` - more explanation can be found in the next section)
92 | - invoke some action on button click (i.e. call logic implemented in vaadin)
93 |
94 | ```javascript
95 | angular.module('weatherModule', ['ngSanitize'])
96 | .controller('WeatherController', function($scope, $connector, $sce) {
97 | $scope.sliderPos = 0;
98 | $scope.content = function() {
99 | var res = $scope.userState.entries[$scope.sliderPos];
100 | return $sce.trustAsHtml(res);
101 | };
102 | $scope.moveSlider = function(val) {
103 | $scope.sliderPos = val;
104 | $scope.sliderUpdated();
105 | };
106 | $scope.sliderUpdated = function() {
107 | $connector.setDeferredVariable("sliderPos", parseInt($scope.sliderPos));
108 | };
109 | $scope.clickButton = function() {
110 | $connector.button_click();
111 | };
112 | });
113 | ```
114 |
115 | There is also a Jasmine test in place for that - you can open */vaangular-demo/src/test/resources/de/akquinet/engineering/vaadin/vaangular/demo/weathertest/weatherTest.html* in a browser to view it (be sure to run `mvn package` once before so all resources are available). A successful run then looks like this:
116 |
117 |
118 |
119 | Nothing so far is mysterious - except that we use `$scope.userState` that seemingly comes out of nowhere. In fact, it is all the data vaadin ships to us - at our fingertips. How you fill the user state is actually explained right below:
120 |
121 | ### Providing a counterpart in vaadin (extending NgTemplate or NgTemplatePlus)
122 |
123 | So what we're still missing from above example is
124 | - filling `$scope.userState`
125 | - something to do with `sliderPos`
126 | - an implementation for `$connector.button_click()`
127 |
128 | In order to do that, there has to be a class `de.akquinet.engineering.vaadin.vaangular.demo.weather.Weather` extending `de.akquinet.engineering.vaadin.vaangular.angular.NgTemplate(Plus)`
129 |
130 | When extending `NgTemplatePlus` (that comes with the [JavaScriptPlus for vaadin](https://github.com/akquinet/JavascriptPlusForvaadin) add-on), you can use deferred variable changes: No call to the server is made until some button click or other (non-deferred) action happens. This dramatically increases responsiveness while reducing (unnecessary) network roundtrips and bandwidth usage. Many standard vaadin components provide this exact behavior via `immediate=false`.
131 |
132 | With this many advantages of deferred variable changes: our example uses those and therefore has to use either a custom widgetset or the pre-compiled widgeset coming with the [JavaScriptPlus for vaadin](https://github.com/akquinet/JavascriptPlusForvaadin) add-on (we do the latter).
133 |
134 | To fill up the user state with some times and weather infos, we provide the following method:
135 | ```java
136 | public void setDaten(int[] times, String[] entries) {
137 | validateParameters(times, entries);
138 | this.times = times;
139 | this.entries = entries;
140 | setUserState("times", times);
141 | setUserState("entries", entries);
142 | markAsDirty();
143 | }
144 | ```
145 |
146 | `setUserState` is provided by NgTemplate / NgTemplatePlus: adding `xyz` to it results in `$scope.userState.xyz` on the client - so `times` results in `$scope.userState.times`. Please observe that changes to this state on the client are not replicated back and overwritten without notice (the standard vaadin behavior). In order to get info from the client to the server, you can either use a method invocation or (provided you use NgTemplatePlus) a deferred variable change. So far, for providing infos to the client, `setUserState`is perfectly OK.
147 |
148 | To work with the slider position (`sliderPos`), we use
149 |
150 | ```javascript
151 | $connector.setDeferredVariable("sliderPos", parseInt($scope.sliderPos));
152 | ```
153 |
154 | on the JavaScript side. On the Java side, we can pull this as follows:
155 |
156 | ```java
157 | public int getSliderPos() {
158 | return Integer.parseInt(getVariables().get("sliderPos").toString());
159 | }
160 | ```
161 |
162 | As the variable change is deferred, no sync to the server happens before a button click. Our example provides a standard vaadin button (`de.akquinet.engineering.vaadin.vaangular.demo.VaangularUI.javaSend`) which (when clicked) shows the currently selected weather info. The following code on click does this:
163 |
164 | ```java
165 | javaSend.addClickListener(new ClickListener() {
166 |
167 | private static final long serialVersionUID = 1L;
168 |
169 | @Override
170 | public void buttonClick(ClickEvent event) {
171 | int index = weatherInfo.getSliderPos();
172 | System.out.println("Button from w/in Java - value: " + index);
173 | showPopup(entries[index]);
174 | }
175 | });
176 | ```
177 |
178 | Upon clicking the button, vaadin does a server roundtrip (as it usually does for buttons). vaadin first processes the deferred variable changes (which is why `de.akquinet.engineering.vaadin.vaangular.angular.NgTemplatePlus.getVariables` yields a correct, up-to-date value) and the invokes the click listener.
179 |
180 | When you open the demo application (along with the Chrome inspector's Network tab), you don't see any server roundtrip when clicking or moving the slider. Only clicking the *E-Mail (from Java)* button produces one.
181 |
182 | Finally, we also want so show how to call the server *immediately* (and how to create a vaadin-like button in pure JavaScript): the *E-Mail (from angular)* is written in AngularJS and invokes vaadin via the following line:
183 |
184 | ```javascript
185 | $connector.button_click();
186 | ```
187 |
188 | On the Java side, we provide a counterpart for this as follows:
189 |
190 | ```java
191 | addService("button", new Object() {
192 | @ServiceMethod
193 | public void click() {
194 | int index = getSliderPos();
195 | System.out.println("Button from w/in angular - value: " + index);
196 | for (WeatherClickListener listener : listeners) {
197 | listener.click(times[index], entries[index]);
198 | }
199 | }
200 | });
201 | ```
202 |
203 | We register such a listener to again display the pop-up.
204 |
205 | So: any class can provide methods to the AngularJS-side as long as their methods are *public* and annotated with `@ServiceMethod` (in fact: `de.akquinet.engineering.vaadin.vaangular.angular.ServiceMethod`). Clicking the button now results in the Java method being called (again with deferred variable changes processed before that).
206 |
207 | ### Getting data from vaadin to AngularJS
208 |
209 | Done by calling `de.akquinet.engineering.vaadin.vaangular.angular.NgTemplatePlus.setUserState(String, Object)` (2nd param must be something that can be turned into JSON). Angular then gets it via `$scope.userState`
210 |
211 | ### Calling vaadin from AngularJS
212 |
213 | Done by calling `de.akquinet.engineering.vaadin.vaangular.angular.NgTemplatePlus.addService(String, Object)` with the 2nd parameter being an implementing a service. Methods to be exposed need to have params that can be derived from JSON and have to be annotated with `@ServiceMethod`. Call from JavaScript via `$connector.service_method`
214 |
215 | ### Deferred variable changes
216 |
217 | Done by calling `$connector.setDeferredVariable` on the JavaScript side (the value will be JSON-serialized). Only available with NgTemplatePlus.
218 |
219 | ## Background
220 |
221 | vaangular solves two essential (and non-obvious) problems:
222 | 1. Delivering JavaScript in a pluggable fashion
223 | 2. Creating an AngularJS *$scope* along with a Controller in it that gets data from vaadin and can communicate back to vaadin
224 |
225 | ### Delivering JavaScript (using @JavaScript)
226 |
227 | vaadin provides a standard method for this via the `@JavaScript` annotation (`com.vaadin.annotations.JavaScript`). In order to include AngularJS, one can e.g. use [WebJars](http://www.webjars.org/) or simply check in the file along with the project.
228 |
229 | ### Creating the AngularJS *$scope*
230 |
231 | The main magic that happens within `NgTemplate.js` is creating a *$scope* for AngularJS. There is one essential challenge: the JavaScript invoked by vaadin is **outside** any AngularJS dependency injection or scope management. Meanwhile, all code you write for AngularJS is obviously **inside** dependency injection and scope management.
232 |
233 | Furthermore, AngularJS assumes (at least per se) that the page's HTML is parsed once and wired up to AngularJS. With vaadin, however, the page's HTML is just some proxy to fire up vaadin magic, and there is nothing to wire up. Even more so, the part with AngularJS in it might be added to a vaadin UI a considerable amount of time after the application was started.
234 |
235 | So, what is needed is an approach to create some new AngularJS-wired-up DOM and Controller on demand from outside AngularJS dependency management / scoping magic.
236 |
237 | vaangular achieves this (in bespoke `NgTemplate.js`) in two steps:
238 |
239 | First, a scope **within** AngularJS is created via
240 | ```javascript
241 | angular.injector([ 'ng', innerModuleName ]).invoke(function($compile, $rootScope) {
242 | ```
243 |
244 | Second, the scope (called `scpe`) and DOM are brought together via
245 | ```javascript
246 | var cmp = $compile(templateElement);
247 | cmp(scpe);
248 | scpe.$digest();
249 | ```
250 |
251 | At the end of this process, we have a new part of the DOM wired up to a new controller - mission accomplished!
252 |
--------------------------------------------------------------------------------
/compile_readme_preview.bat:
--------------------------------------------------------------------------------
1 | pandoc README.md -o README.html -f markdown_github
--------------------------------------------------------------------------------
/img/demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akquinet/vaangular/deff1191ce81bbe0a1d342f8524b4c9d69588433/img/demo.png
--------------------------------------------------------------------------------
/img/jasmine.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akquinet/vaangular/deff1191ce81bbe0a1d342f8524b4c9d69588433/img/jasmine.png
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
19 |
20 | 4.0.0
21 |
22 | de.akquinet.engineering.vaadin.vaangular
23 | vaangular-parent
24 | 0.1.3-SNAPSHOT
25 | pom
26 |
27 |
33 |
34 |
35 | vaangular
36 | vaangular-demo
37 |
38 |
39 |
119 |
120 |
121 |
--------------------------------------------------------------------------------
/vaangular-demo/VaangularApplication.launch:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/vaangular-demo/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
19 |
20 |
26 |
27 | 4.0.0
28 |
29 | de.akquinet.engineering.vaadin.vaangular
30 | vaangular-demo
31 |
32 | 0.1.3-SNAPSHOT
33 |
34 |
35 | 1.2.1.RELEASE
36 |
37 | UTF-8
38 | 7.7.3
39 | 2.2.4
40 |
41 |
42 |
43 |
44 | de.akquinet.engineering.vaadin.vaangular
45 | vaangular
46 | ${project.version}
47 |
48 |
49 | de.akquinet.engineering
50 | javascriptplus-for-vaadin
51 |
52 |
54 | 0.1.2
55 |
56 |
57 | org.springframework.boot
58 | spring-boot-starter
59 | ${spring-boot.version}
60 |
61 |
62 | org.springframework.boot
63 | spring-boot-starter-web
64 | ${spring-boot.version}
65 |
66 |
67 | org.springframework.boot
68 | spring-boot-starter-jetty
69 | ${spring-boot.version}
70 |
71 |
72 | org.springframework.boot
73 | spring-boot-starter-actuator
74 | ${spring-boot.version}
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | org.apache.maven.plugins
84 | maven-compiler-plugin
85 | 2.3.2
86 |
87 | 1.8
88 | 1.8
89 | UTF-8
90 |
91 |
92 |
93 |
94 | org.apache.maven.plugins
95 | maven-resources-plugin
96 | 2.6
97 |
98 | UTF-8
99 |
100 |
101 |
102 |
103 | com.vaadin
104 | vaadin-maven-plugin
105 | ${vaadin.version}
106 |
107 | ${project.build.directory}/${project.build.finalName}stage/VAADIN/widgetsets
108 | -Xmx512M -Xss1024k
109 | true
110 |
111 |
112 |
113 |
114 | resources
115 | compile
116 |
117 |
118 |
119 |
120 |
121 |
122 | org.apache.maven.plugins
123 | maven-dependency-plugin
124 | 2.10
125 |
126 |
127 | unpack
128 | generate-resources
129 |
130 | unpack
131 |
132 |
133 |
134 |
135 | org.webjars
136 | angularjs
137 | 1.3.15
138 | jar
139 | META-INF/resources/webjars/angularjs/1.3.15/**/*
140 | ${project.build.directory}/jsunpack/de/akquinet/engineering/vaadin/vaangular/demo/weather
141 |
142 |
143 |
144 |
145 |
146 | unpackTest
147 | generate-test-resources
148 |
149 | unpack
150 |
151 |
152 |
153 |
154 | org.webjars
155 | jasmine
156 | 2.2.0
157 | jar
158 | META-INF/resources/webjars/jasmine/2.2.0/**/*
159 | ${project.build.directory}/jsunpackTest/de/akquinet/engineering/vaadin/vaangular/demo/weathertest
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 | src/main/resources
170 |
171 |
172 | ${project.build.directory}/jsunpack
173 | false
174 |
175 |
176 |
177 |
178 | src/test/resources
179 |
180 |
181 | ${project.build.directory}/jsunpackTest
182 | false
183 |
184 |
185 |
186 |
187 |
188 |
189 | vaadin-addons
190 | http://maven.vaadin.com/vaadin-addons
191 |
192 |
193 |
194 |
195 |
--------------------------------------------------------------------------------
/vaangular-demo/src/main/java/de/akquinet/engineering/vaadin/vaangular/demo/VaangularApplication.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 akquinet engineering GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 | package de.akquinet.engineering.vaadin.vaangular.demo;
17 |
18 | import javax.servlet.Servlet;
19 |
20 | import org.springframework.boot.SpringApplication;
21 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
22 | import org.springframework.boot.builder.SpringApplicationBuilder;
23 | import org.springframework.boot.context.embedded.RegistrationBean;
24 | import org.springframework.boot.context.embedded.ServletRegistrationBean;
25 | import org.springframework.boot.context.web.SpringBootServletInitializer;
26 | import org.springframework.context.ApplicationContext;
27 | import org.springframework.context.annotation.Bean;
28 | import org.springframework.context.annotation.ComponentScan;
29 | import org.springframework.context.annotation.Configuration;
30 |
31 | @Configuration
32 | @ComponentScan
33 | @EnableAutoConfiguration
34 | public class VaangularApplication extends SpringBootServletInitializer
35 | {
36 |
37 | @Bean
38 | public RegistrationBean vaangularServlet(final ApplicationContext context)
39 | {
40 | final Servlet servlet = new VaangularServlet();
41 | return new ServletRegistrationBean(servlet, "/*");
42 | }
43 |
44 | @Override
45 | protected SpringApplicationBuilder configure(final SpringApplicationBuilder application)
46 | {
47 | return application.sources(VaangularApplication.class);
48 | }
49 |
50 | public static void main(final String... args)
51 | {
52 | SpringApplication.run(VaangularApplication.class, args);
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/vaangular-demo/src/main/java/de/akquinet/engineering/vaadin/vaangular/demo/VaangularServlet.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 akquinet engineering GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 | package de.akquinet.engineering.vaadin.vaangular.demo;
17 |
18 | import javax.servlet.annotation.WebServlet;
19 |
20 | import com.vaadin.annotations.VaadinServletConfiguration;
21 | import com.vaadin.server.VaadinServlet;
22 |
23 | @WebServlet()
24 | @VaadinServletConfiguration(ui = VaangularUI.class, productionMode = false, widgetset = "de.akquinet.engineering.vaadin.javascriptplus.JavaScriptPlusForVaadin")
25 | public class VaangularServlet extends VaadinServlet {
26 |
27 | private static final long serialVersionUID = 1L;
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/vaangular-demo/src/main/java/de/akquinet/engineering/vaadin/vaangular/demo/VaangularUI.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 akquinet engineering GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 | package de.akquinet.engineering.vaadin.vaangular.demo;
17 |
18 | import com.vaadin.annotations.PreserveOnRefresh;
19 | import com.vaadin.annotations.Theme;
20 | import com.vaadin.server.VaadinRequest;
21 | import com.vaadin.shared.ui.label.ContentMode;
22 | import com.vaadin.ui.Accordion;
23 | import com.vaadin.ui.Button;
24 | import com.vaadin.ui.Button.ClickEvent;
25 | import com.vaadin.ui.Button.ClickListener;
26 | import com.vaadin.ui.Label;
27 | import com.vaadin.ui.UI;
28 | import com.vaadin.ui.VerticalLayout;
29 | import com.vaadin.ui.Window;
30 |
31 | import de.akquinet.engineering.vaadin.vaangular.demo.weather.Weather;
32 | import de.akquinet.engineering.vaadin.vaangular.demo.weather.Weather.WeatherClickListener;
33 |
34 | @Theme("valo")
35 | @PreserveOnRefresh
36 | public class VaangularUI extends UI {
37 |
38 | private static final long serialVersionUID = 1L;
39 |
40 | protected Weather weatherInfo;
41 | protected Button javaSend;
42 |
43 | /*
44 | * (non-Javadoc)
45 | *
46 | * @see com.vaadin.ui.UI#init(com.vaadin.server.VaadinRequest)
47 | */
48 | @Override
49 | protected void init(VaadinRequest request) {
50 |
51 | try {
52 |
53 | VerticalLayout mainLayout = new VerticalLayout();
54 | mainLayout.setMargin(true);
55 | mainLayout.setSpacing(true);
56 | Accordion accordion = new Accordion();
57 |
58 | weatherInfo = new Weather();
59 | final int[] times = new int[] { 10, 12, 14, 16 };
60 | final String[] entries = new String[] {
61 | "10° sunny", "12° windy",
62 | "14° cold", "20° superb" };
63 | weatherInfo.setDaten(times, entries);
64 | weatherInfo.addClickListener(new WeatherClickListener() {
65 |
66 | private static final long serialVersionUID = 1L;
67 |
68 | @Override
69 | public void click(int time, String entry) {
70 | showPopup(entry);
71 | }
72 | });
73 | weatherInfo.setButtonCaption("E-Mail (from angular)");
74 | accordion.addTab(weatherInfo, "Weather-Demo");
75 | mainLayout.addComponent(accordion);
76 |
77 | javaSend = new Button();
78 | javaSend.setCaption("E-Mail (from Java)");
79 | javaSend.addClickListener(new ClickListener() {
80 |
81 | private static final long serialVersionUID = 1L;
82 |
83 | @Override
84 | public void buttonClick(ClickEvent event) {
85 | int index = weatherInfo.getSliderPos();
86 | System.out.println("Button from w/in Java - value: "
87 | + index);
88 | showPopup(entries[index]);
89 | }
90 | });
91 | mainLayout.addComponent(javaSend);
92 |
93 | setContent(mainLayout);
94 | } catch (Exception e) {
95 | throw new RuntimeException("some stupid error occured!", e);
96 | }
97 | }
98 |
99 | private void showPopup(String eintrag) {
100 | Window modalWin = new Window("E-Mail is being sent...");
101 | modalWin.setContent(new Label("
"
102 | + "
Season's greetings
" + "
" + eintrag + "
"
103 | + "
", ContentMode.HTML));
104 | modalWin.setModal(true);
105 | modalWin.setWidth("400px");
106 | modalWin.setHeight("250px");
107 | modalWin.center();
108 | UI.getCurrent().addWindow(modalWin);
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/vaangular-demo/src/main/java/de/akquinet/engineering/vaadin/vaangular/demo/weather/Weather.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 akquinet engineering GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 | package de.akquinet.engineering.vaadin.vaangular.demo.weather;
17 |
18 | import java.io.IOException;
19 | import java.net.URISyntaxException;
20 | import java.util.ArrayList;
21 | import java.util.List;
22 |
23 | import com.vaadin.annotations.JavaScript;
24 | import com.vaadin.event.ConnectorEventListener;
25 |
26 | import de.akquinet.engineering.vaadin.vaangular.angular.NgTemplatePlus;
27 | import de.akquinet.engineering.vaadin.vaangular.angular.ServiceMethod;
28 |
29 | @JavaScript({ "META-INF/resources/webjars/angularjs/1.3.15/angular.js",
30 | "META-INF/resources/webjars/angularjs/1.3.15/angular-sanitize.js",
31 | "weather.js" })
32 | public class Weather extends NgTemplatePlus {
33 |
34 | /**
35 | *
36 | */
37 | private static final long serialVersionUID = -1857536974366619130L;
38 |
39 | private List listeners = new ArrayList();
40 |
41 | private int[] times;
42 | private String[] entries;
43 |
44 | public Weather() throws IOException, URISyntaxException {
45 | super(Weather.class.getPackage(), "weatherModule");
46 | addService("button", new Object() {
47 | @ServiceMethod
48 | public void click() {
49 | int index = getSliderPos();
50 | System.out
51 | .println("Button from w/in angular - value: " + index);
52 | for (WeatherClickListener listener : listeners) {
53 | listener.click(times[index], entries[index]);
54 | }
55 | }
56 | });
57 | setButtonCaption("senden");
58 | }
59 |
60 | public void setButtonCaption(String caption) {
61 | setUserState("buttonCaption", caption);
62 | }
63 |
64 | public int getSliderPos() {
65 | return Integer.parseInt(getVariables().get("sliderPos").toString());
66 | }
67 |
68 | public void setDaten(int[] times, String[] entries) {
69 | validateParameters(times, entries);
70 | this.times = times;
71 | this.entries = entries;
72 | setUserState("times", times);
73 | setUserState("entries", entries);
74 | markAsDirty();
75 | }
76 |
77 | static void validateParameters(int[] times, String[] entries) {
78 | if (times.length != entries.length) {
79 | throw new IllegalArgumentException("#times does not match #entries");
80 | }
81 | if (times.length < 2) {
82 | throw new IllegalArgumentException(
83 | "#times/#entries needs to be >=2");
84 | }
85 | int step = calcStep(times);
86 | for (int i = 1; i < times.length; i++) {
87 | if (!(times[i - 1] < times[i])) {
88 | throw new IllegalArgumentException("Times must be in order");
89 | }
90 | if ((times[i] - times[i - 1]) != step) {
91 | throw new IllegalArgumentException(
92 | "Times must have same delta between one another");
93 | }
94 | }
95 | }
96 |
97 | private static int calcStep(int[] times) {
98 | int step = times[1] - times[0];
99 | return step;
100 | }
101 |
102 | public void addClickListener(WeatherClickListener listener) {
103 | listeners.add(listener);
104 | }
105 |
106 | public void removeClickListener(WeatherClickListener listener) {
107 | listeners.remove(listener);
108 | }
109 |
110 | public interface WeatherClickListener extends ConnectorEventListener {
111 |
112 | public void click(int time, String entry);
113 | }
114 |
115 | }
116 |
--------------------------------------------------------------------------------
/vaangular-demo/src/main/resources/application.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akquinet/vaangular/deff1191ce81bbe0a1d342f8524b4c9d69588433/vaangular-demo/src/main/resources/application.properties
--------------------------------------------------------------------------------
/vaangular-demo/src/main/resources/de/akquinet/engineering/vaadin/vaangular/demo/weather/weather.html:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
21 |
{{zeit}}
:00
22 |
23 |
24 |
25 |
26 |
27 | {{userState.buttonCaption}}
28 |
29 |
30 |
--------------------------------------------------------------------------------
/vaangular-demo/src/main/resources/de/akquinet/engineering/vaadin/vaangular/demo/weather/weather.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 akquinet engineering GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 | angular.module('weatherModule', ['ngSanitize'])
17 | .controller('WeatherController', function($scope, $connector, $sce) {
18 | $scope.sliderPos = 0;
19 | $scope.content = function() {
20 | var res = $scope.userState.entries[$scope.sliderPos];
21 | return $sce.trustAsHtml(res);
22 | };
23 | $scope.moveSlider = function(val) {
24 | $scope.sliderPos = val;
25 | $scope.sliderUpdated();
26 | };
27 | $scope.sliderUpdated = function() {
28 | $connector.setDeferredVariable("sliderPos", parseInt($scope.sliderPos));
29 | };
30 | $scope.clickButton = function() {
31 | $connector.button_click();
32 | };
33 | });
--------------------------------------------------------------------------------
/vaangular-demo/src/test/resources/de/akquinet/engineering/vaadin/vaangular/demo/weathertest/weatherSpec.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 akquinet engineering GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 | describe("Weather base suite", function() {
17 | var $rootScope, $connector, $sce, createController;
18 | beforeEach(module("weatherModule"));
19 | beforeEach(inject(function($injector) {
20 | $rootScope = $injector.get('$rootScope');
21 | $rootScope.userState={};
22 | $connector = {
23 | setDeferredVariable : function() {
24 | },
25 | button_click : function() {
26 | }
27 | };
28 | $sce = {
29 | trustAsHtml : function(str){
30 | return str;
31 | }
32 | };
33 | var $controller = $injector.get('$controller');
34 | createController = function() {
35 | return $controller('WeatherController', {
36 | '$scope' : $rootScope,
37 | '$connector' : $connector,
38 | '$sce' : $sce
39 | });
40 | };
41 | }));
42 | it("displays initial content", function() {
43 | var controller = createController();
44 | $rootScope.sliderPos = 2;
45 | $rootScope.userState.entries = [ "zero", "one", "two", "three" ];
46 | expect($rootScope.content()).toEqual("two");
47 | });
48 | it("displays content based on slider", function() {
49 | var controller = createController();
50 | $rootScope.sliderPos = 2;
51 | $rootScope.userState.entries = [ "zero", "one", "two", "three" ];
52 | spyOn($connector, 'setDeferredVariable');
53 | $rootScope.moveSlider(1);
54 | expect($rootScope.content()).toEqual("one");
55 | expect($connector.setDeferredVariable).toHaveBeenCalledWith("sliderPos", 1);
56 | });
57 | it("reacts on slider change", function() {
58 | var controller = createController();
59 | $rootScope.sliderPos = 2;
60 | $rootScope.userState.entries = [ "zero", "one", "two", "three" ];
61 | spyOn($connector, 'setDeferredVariable');
62 | $rootScope.sliderPos = 1;
63 | $rootScope.sliderUpdated();
64 | expect($rootScope.content()).toEqual("one");
65 | expect($connector.setDeferredVariable).toHaveBeenCalledWith("sliderPos", 1);
66 | });
67 | it("button calls to vaadin", function() {
68 | var controller = createController();
69 | spyOn($connector, 'button_click');
70 | $rootScope.clickButton();
71 | expect($connector.button_click).toHaveBeenCalled();
72 | });
73 | });
--------------------------------------------------------------------------------
/vaangular-demo/src/test/resources/de/akquinet/engineering/vaadin/vaangular/demo/weathertest/weatherTest.html:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 | Jasmine Spec Runner v2.0.0
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/vaangular/assembly/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Vaadin-Package-Version: 1
3 | Vaadin-Addon: ${vaadin.addon}
4 | Vaadin-License-Title: ${vaadin.license.title}
5 | Implementation-Vendor: ${implementation.vendor}
6 | Implementation-Title: ${implementation.title}
7 | Implementation-Version: ${implementation.version}
8 |
--------------------------------------------------------------------------------
/vaangular/assembly/assembly.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
21 | addon
22 |
23 |
24 | zip
25 |
26 |
27 | false
28 |
29 |
30 |
31 | ..
32 |
33 | LICENSE
34 | README.md
35 |
36 |
37 |
38 | target
39 |
40 |
41 | *.jar
42 |
43 |
44 |
45 |
46 |
47 |
48 | assembly/MANIFEST.MF
49 | META-INF
50 | true
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/vaangular/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
19 |
20 |
26 |
27 | 4.0.0
28 |
29 | de.akquinet.engineering.vaadin.vaangular
30 | vaangular
31 |
32 | 0.1.3-SNAPSHOT
33 |
34 |
35 | ${project.version}
36 | vaangular
37 | akquinet engineering GmbH
38 | Apache License Version 2.0
39 | ${project.artifactId}-${project.version}.jar
40 |
41 | UTF-8
42 | 7.7.3
43 | 2.2.4
44 |
45 |
46 |
47 |
48 |
49 | com.vaadin
50 | vaadin-server
51 |
52 | ${vaadin.version}
53 |
54 |
55 | com.vaadin
56 | vaadin-themes
57 |
58 | ${vaadin.version}
59 |
60 |
61 |
62 | com.google.code.gson
63 | gson
64 |
65 | ${gson.version}
66 |
67 |
68 |
69 | de.akquinet.engineering
70 | javascriptplus-for-vaadin
71 | true
72 |
73 | 0.1.3-SNAPSHOT
74 |
75 |
76 |
77 | junit
78 | junit
79 | test
80 |
81 | 4.10
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 | org.apache.maven.plugins
92 | maven-compiler-plugin
93 | 2.3.2
94 |
95 | 1.8
96 | 1.8
97 | UTF-8
98 |
99 |
100 |
101 |
102 | org.apache.maven.plugins
103 | maven-resources-plugin
104 | 2.6
105 |
106 | UTF-8
107 |
108 |
109 |
110 |
111 | com.vaadin
112 | vaadin-maven-plugin
113 | ${vaadin.version}
114 |
115 | ${project.build.directory}/${project.build.finalName}stage/VAADIN/widgetsets
116 | -Xmx512M -Xss1024k
117 | true
118 |
119 |
120 |
121 |
122 | resources
123 | compile
124 |
125 |
126 |
127 |
128 |
129 |
130 | org.apache.maven.plugins
131 | maven-jar-plugin
132 | 2.5
133 |
134 |
135 | true
136 |
137 | true
138 |
139 |
140 |
141 | 1
142 | ${implementation.title}
143 | ${vaadin.license.title}
144 |
145 |
146 |
147 |
148 |
149 |
150 | org.apache.maven.plugins
151 | maven-assembly-plugin
152 | 2.5.3
153 |
154 | ${project.artifactId}
155 | false
156 |
157 | assembly/assembly.xml
158 |
159 |
160 |
161 |
162 |
163 | single
164 |
165 | package
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
--------------------------------------------------------------------------------
/vaangular/src/main/java/de/akquinet/engineering/vaadin/vaangular/angular/MethodInvoker.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 akquinet engineering GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 | package de.akquinet.engineering.vaadin.vaangular.angular;
17 |
18 | import com.vaadin.ui.JavaScriptFunction;
19 |
20 | import elemental.json.JsonArray;
21 |
22 | import java.lang.reflect.InvocationTargetException;
23 | import java.lang.reflect.Method;
24 | import java.util.ArrayList;
25 | import java.util.List;
26 |
27 | /**
28 | * @author Axel Meier, akquinet engineering GmbH
29 | */
30 | public class MethodInvoker implements JavaScriptFunction {
31 | private static final long serialVersionUID = 1L;
32 |
33 | private final Object object;
34 | private final Method method;
35 |
36 | public MethodInvoker(final Object object, final Method method) {
37 | this.object = object;
38 | this.method = method;
39 | }
40 |
41 | @Override
42 | public void call(final JsonArray arguments) {
43 | try {
44 | final Class>[] paramTypes = method.getParameterTypes();
45 | final List