angularjs $scope form undefined

Was developing some form with angular, things work perfect until I add a angular-ui bootstrap tab to enclose 2 different form in each tab.

when i try to access the form with $scope.formName, the formName is undefined.

It turns out that the angularUI tab directive uses transclude which will create a child scope to the parent which here is the controller $scope as the sibling of the directive scope. Then the formName can only be access by the new child scope.

One solution is define a var in the controller scope like $scope.forms = {};

Then for the form name in the transclude directive, we use forms.formName1. This way we could still access it from our controller by just call $scope.forms.formName1.

This works because the inheritance mechanism in JS is prototype chain. So when child scope tries to create the forms.formName1, it first tries to find the forms object in its own scope which definitely does not have it since it is created on the fly. Then it will try to find it from the parent(up to the prototype chain) and since we have it defined in the controller scope, it uses this ‘forms’ object we created to define the variable formName1. As a result we could still use it in the controller like $scope.forms.formName1.$valild to do our stuff.

Advertisements

form submit on enter when one input text

Got an odd behavior today when dealing with a form which has only one input.

The input binds to a js function to judge if it is key==13, we do tweak the input params and submit. However everytime we hit enter, even before executing the js function, the form has already been submitted to the server.

Turns out:

In the HTML 2.0 specification, in the section entitled Form Submission, logically enough:

When there is only one single-line text input field in a form, the user agent should accept Enter in that field as a request to submit the form.

So to prevent this. a easy way is to put a hidden input box in the form.

<input class="hide"/>

Hide is just a bootstrap class which has

display: none!important;

angularjs form validation

Official documentation is pretty good.

novalidate is used to disable browser’s native form validation.

A form is an instance of FormController. The form instance can optionally be published into the scope using the name attribute.

Similarly, an input control that has the ngModel directive holds an instance of NgModelController. Such a control instance can be published as a property of the form instance using the name attribute on the input control. The name attribute specifies the name of the property on the form instance.

This implies that the internal state of both the form and the control is available for binding in the view using the standard binding primitives.

This allows us to extend the above example with these features:

  • Custom error message displayed after the user interacted with a control (i.e. when $touched is set)
  • Custom error message displayed upon submitting the form ($submitted is set), even if the user didn’t interact with a control

By default, any change to the content will trigger a model update and form validation. You can override this behavior using thengModelOptions directive to bind only to specified list of events. I.e. ng-model-options="{ updateOn: 'blur' }" will update and validate only after the control loses focus. You can set several events using a space delimited list. I.e.ng-model-options="{ updateOn: 'mousedown blur' }"

Custom validation could be added thru directive by calling ngModel.$validators.customField = function(modelValue, viewValue){// true or false logic}

Async custom validation uses $asyncValidators and should return a promise.

To modify the built in validation, just overwrite the corresponding field in $validators in link function:

ctrl.$validators.email = function(modelValue) {
          return ctrl.$isEmpty(modelValue) || EMAIL_REGEXP.test(modelValue);
        };

require: ‘ngModel’

Note many of the link function has

require: 'ngModel',

It means :

The require instruction gives you the controller for the directive you name as the fourth argument to your link function. (You can use ^ to look for the controller on a parent element; ? makes it optional.) So require: 'ngModel' gives you the controller for the ngModel directive, which is an ngModelController.

Directive controllers can be written to provide APIs that other directives can use; with ngModelController, you get access to special functionality that’s built into ngModel, including getting and setting the value. Consider the following example:

<input color-picker ng-model="project.color">
app.directive('colorPicker', function() {
  return {
    require: 'ngModel',
    link: function(scope, element, attrs, ngModel) {
      element.colorPicker({
        // initialize the color to the color on the scope
        pickerDefault: scope.color,
        // update the ngModel whenever we pick a new color
        onColorChange: function(id, newValue) {
          scope.$apply(function() {
            ngModel.$setViewValue(newValue);
          });
        }
      });

      // update the color picker whenever the value on the scope changes
      ngModel.$render = function() {
        element.val(ngModel.$modelValue);
        element.change();                
      };
    }
  }
});

This directive uses the ngModel controller to get and set the value of the color from the colorpicker. See this JSFiddle example: http://jsfiddle.net/BinaryMuse/AnMhx/

If you’re using require: 'ngModel', you probably shouldn’t also be using ngModel: '=' in your isolate scope; the ngModelController gives you all the access you need to change the value.

The bottom example on the AngularJS homepage also uses this functionality (except using a custom controller, not ngModel).

html form submission type

When you make a POST request, you have to encode the data that forms the body of the request in some way.

HTML forms provide three methods of encoding.

  • application/x-www-form-urlencoded (the default)
  • multipart/form-data
  • text/plain

Work is being done on adding application/json.

The specifics of the formats don’t matter to most developers. The important points are:

When you are writing client-side code, all you need to know is use multipart/form-data when your form includes any <input type="file"> elements.

When you are writing server-side code: Use a prewritten form handling library (e.g. Perl’s CGI->param or the one exposed by PHP’s $_POST superglobal) and it will take care of the differences for you. Don’t bother trying to parse the raw input received by the server.

Never use text/plain.


If you are writing (or debugging) a library for parsing or generating the raw data, then you need to start worrying about the format. You might also want to know about it for interest’s sake.

application/x-www-form-urlencoded is more or less the same as a query string on the end of the URL.

multipart/form-data is significantly more complicated but it allows entire files to be included in the data. An example of the result can be found in the HTML 4 specification.

text/plain is introduced by HTML and is useful only for debugging — from the spec: They are not reliably interpretable by computer — and I’d argue that the others combined with tools (like the Net tab in the developer tools of most browsers) are better for that).

primeface update current table

I have a data table. Each row of the table has a commandButton called ‘Remove’, which is supposed to remove that row from the model and the view and perform an update in-place.

when I click a button on one of the rows, to remove it, it partially works. The corresponding element is removed from the model but the view is not updated.

update=”userTable” is the way in this situation.

I tried : update=”:usersForm:userTable” not working.

Finally the update=”@form” works for me.

 

Another issue is if the commandButton and the update component are not in the same form, the explicit location must be specified just like : update=”:otherFormId:tableToBeUpdatedId”. Even if the component is in the top level, the colon is still necessary for the id. For example, the growl is something very common, we need to updated this way: update=”:growl”

 

create ajax State-City of U.S selection in Primefaces

Steps:
  1. get all state, city info of U.S from HERE . There are also many other data could be freely download from this site.
  2. dump the dbf file to sql.
  3. create tables in mysql and import all data
  4. create UI and backing beans for the data.

UI:

<h:outputLabel for="state" value="state: *" />

<p:selectOneMenu id="state" value="#{userManager.potentialUser.state}">

<f:selectItem itemLabel="Select State" itemValue="" />

<f:selectItems value="#{stateCityManager.states}" />

<p:ajax<span style="color: #ff0000;"> update="city" </span>listener="#{stateCityManager.handleStateChange}" />

</p:selectOneMenu>

<h:outputLabel for="city" value="city: *" />

<p:selectOneMenu id="city" value="#{userManager.potentialUser.city}">

<f:selectItem itemLabel="Select City" itemValue="" />

<f:selectItems value="#{stateCityManager.cities}" />

</p:selectOneMenu>

Spring Bean:

@Component("stateCityManager")

@Scope("session")

public class StateCityManager {

public StateCityManager() {

}

@Inject

StateCityDao stateCityDao;

private List&lt;String&gt; states;

private List&lt;String&gt; cities;

private UserManager userManager;

public UserManager getUserManager() {

return userManager;

}

@Autowired

public void setUserManager(UserManager userManager) {

this.userManager = userManager;

}

//private String state = userManager.getPotentialUser().getState();    //can not use a private field to connect values between components, otherwise NPE.

@PostConstruct

public void init() {

loadStates();

}

public void loadStates(){

states = stateCityDao.getAllStates();

cities = new ArrayList&lt;String&gt;();

}

<span style="color:#ff0000;">public void handleStateChange() {  </span>

<span style="color:#ff0000;">        if(userManager.getPotentialUser().getState() !=null &amp;&amp; !userManager.getPotentialUser().getState().equals(""))  </span>

<span style="color:#ff0000;">            cities = stateCityDao.getCitiesByState(userManager.getPotentialUser().getState());  </span>

<span style="color:#ff0000;">        else  </span>

<span style="color:#ff0000;">            cities = new ArrayList&lt;String&gt;();  </span>

<span style="color:#ff0000;"> }  </span>}

 </div>
 <div></div>
 <div></div>
 <div>DAO</div>
 <div>
@Repository

@Transactional

public class StateCityDaoImpl extends BaseDaoImpl implements StateCityDao {

@Override

public List&lt;String&gt; getAllStates() throws DataAccessException {

@SuppressWarnings("unchecked")

List&lt;String&gt; results = em.createNamedQuery("StateCity.findAllStates").getResultList();

if (results == null) {

results = new ArrayList&lt;String&gt;();

}

return results;

}

@Override

public List&lt;String&gt; getCitiesByState(String state)

throws DataAccessException {

@SuppressWarnings("unchecked")

List&lt;String&gt; results = em.createNamedQuery("StateCity.findCitiesByState").setParameter("state", state).getResultList();

if (results == null) {

results = new ArrayList&lt;String&gt;();

}

return results;

}

}