NgAndroid
NgAndroid provides two-way data binding and MVC to Android. It accomplishes this using compile time annotation processing and Java source generation which makes the bindings type safe and effecient.
the latest version NgAndroid is in an unstable beta and is subject to API changes. The readme to a more stable version can be found here
NgAndroid can be added as a gradle dependency:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
}
}
allprojects {
repositories {
maven {
url 'http://oss.sonatype.org/content/repositories/snapshots'
}
}
}
apply plugin: 'com.neenbedankt.android-apt' dependencies {
compile 'com.github.davityle:ngandroid:1.0.10-SNAPSHOT'
apt 'com.github.davityle:ng-processor:1.0.10-SNAPSHOT'
}
Usage
NgAndoid works by generating a controller class and event binding models using two annotations (subject to change) @NgModel
and @NgScope
. You can read more about them below. After you have annotated a class with @NgScope
and referenced it in your xml file a controller will be generated for that xml file. If I created a scope class MyScope
and referenced it in an xml layout login.xml
a controller called LoginController
would be created for the xml layout. To bind your scope to your layout you would instaniate the controller, passing in the scope, and call LoginController#attach(android.view.View view)
passing in the view. For example
View v = inflater.inflate(R.layout.login, container, false);
MyScope scope = new MyScope();
LoginController controller = new LoginController(new NgOptions.Builder().build(), scope) controller.attach(v);
@NgModel
@NgModel
marks a field within a scope as a model that can be bound to views. Any field that is marked as a model will be injected into the scope automatically. This is imporant because ngAndroid will create a subclass of the Model that triggers events when it is changed and somthing is listening to those changes.
The type of any field marked with @NgModel
should have getters and setters declared for each of it's fields.
@NgScope
@NgScope
marks a class as a scope. A scope is the base reference for any data binding reference.
@NgScope(name="Login") public class LoginScope {
@NgModel
User user;
void onSubmit(/*any paramaters*/) {
// submission code
}
}
To use a scope you set the ngScope attribute in your xml to the name of the scope. For example if I were to use the above scope I would add
<RelativeLayout ...
xmlns:x="http://schemas.android.com/apk/res-auto"
x:ngScope="Login">
to my layout. I could then reference any methods or models declared in the scope in my xml bindings.
<EditText ...
x:ngModel="user.username" /> <EditText
x:ngModel="user.password"/> <Button ...
x:ngDisabled="user.username.length() < 6 || user.password.length() < 6"
x:ngClick="onSubmit($view.context)"/>
Attributes
NgModel Two way data binding
NgText One way data to text view binding
NgClick Click event binding
NgLongClick Long click event binding
NgDisabled Two way boolean data binding to view disabled state
NgInvisible Two way boolean data binding to view invisible state
NgGone Two way boolean data binding to view gone state
NgFocus Two way boolean data binding to view focus state
Common Gotchas
Coming Soon
ngRepeat ngChange deep integration with injection of scopes and models using Dagger 2
All examples are using this model
public class Input {
private String input;
private int integer;
private boolean disabled;
private boolean gone;
private boolean invisible;
private boolean blur;
private boolean focus;
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
public int getInteger() {
return integer;
}
public void setInteger(int integer) {
this.integer = integer;
}
public boolean getDisabled() {
return disabled;
}
public void setDisabled(boolean disabled) {
this.disabled = disabled;
}
public boolean getGone() {
return gone;
}
public void setGone(boolean gone) {
this.gone = gone;
}
public boolean getInvisible() {
return invisible;
}
public void setInvisible(boolean invisible) {
this.invisible = invisible;
}
public boolean getBlur() {
return blur;
}
public void setBlur(boolean blur) {
this.blur = blur;
}
public boolean getFocus() {
return focus;
}
public void setFocus(boolean focus) {
this.focus = focus;
}
}
ngModel
<!-- add xml attributes --> <EditText
android:id="@+id/edit_text"
x:ngModel="input.input"
... />
<TextView
android:id="@+id/text_view"
x:ngModel="input.input"
.../>
ngClick
<Button
android:id="@+id/click_event"
x:ngClick="onClickEvent()"
.../>
void onClickEvent(){
// do something
}
ngLongClick
<Button
android:id="@+id/multiplyButton"
x:ngClick="multiply(input.integer,2)"
x:ngLongClick="multiply(3,input.integer)"
.../>
void multiply(int num1, int num2){
// do something
}
ngDisabled
<CheckBox
android:id="@+id/ngdisabledcheckbox"
x:ngModel="input.disabled"
... /> <Button
android:id="@+id/an_id_is_required_for_any_ng_android_binding"
x:ngDisabled="input.disabled"
.../>
ngInvisible
<Button
android:id="@+id/nginvisible"
x:ngInvisible="input.invisible"
.../> <CheckBox
android:id="@+id/ngvisiblecb"
x:ngModel="input.invisible"
.../>
ngGone
<Button
android:id="@+id/nggone"
x:ngGone="input.gone"
.../> <CheckBox
android:id="@+id/nggonedb"
x:ngModel="input.gone"
... />
Gotchas:
Each view that has an ngangular attribute must also have an id
Feedback and contributions are encouraged
" AngularJS logo.svg" by AngularJS is licensed under Creative Commons Attribution-ShareAlike 3.0 Unported License