Skip to content

fieldId()'s for names and ids #560

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

plong0
Copy link

@plong0 plong0 commented Sep 29, 2015

decorators should be updated (typically) by:
replacing:
form.key.slice(-1)[0]
with:
fieldId() in name attributes
fieldId(true) in id/for/aria-describedby attributes

@plong0 plong0 mentioned this pull request Sep 29, 2015
@davidlgj
Copy link
Contributor

Edit: Sorry @plong I saw the former PR, you explained it there. Goldfish memory...

Hi @plong0 there are a couple of PR's handling id's and names right now so I'll try to make a good
solution out of all of them.

Could you describe a bit more what the fieldId() method does? What problem does it solve?

@plong0
Copy link
Author

plong0 commented Sep 30, 2015

cheers :)
to further elaborate:

scope.fieldId = function(prependFormName, omitNumbers) { ... };
generates a hyphen-delimited ID based on scope.form.key

prependFormName - when true and there is a ?^form controller, prepends the form's $name to the return value (useful for unique id attributes when multiple forms on a page)

omitNumbers - when true, omits numerical key entries (array indexes) from the returned id (useful for generating a class name)

the 3 use cases I've implemented with it:
fieldId(false, true) - for appending to the htmlClass
fieldId(true) - for generating id/for attributes
fieldId() - for generating name attributes

@AndyStricker
Copy link

I've found this pull request after looking for a solution to the unique identifier problem I have. Some bootstrap decorators use <label for="x"></label> and <input id="x"> (e.g. default.html and textarena.html): If more than one instance of the same form is used, then clicking on a label jumps to the wrong form sometime. Using this fieldId(true) with an unique form name will solve this. I'm willing to contribute the necessary code changes to the new and old bootstrap decorator using this function if this pull request is merged.

@plong0
Copy link
Author

plong0 commented Apr 8, 2016

@AndyStricker hey that would be awesome if you could help get this merged! :)

I've just been using my forked branch for this + a couple other changes/fixes I needed for my project. I would be really happy if they could all get merged and I could come back to the official repo.

@Anthropic
Copy link
Member

@plong0 @AndyStricker I'll take a look tomorrow, I actually implemented something similar for the Material decorator already, so I'm sure we can get something in a release soon.

@AndyStricker
Copy link

@Anthropic: Thanks for the hint, do you mean the sfCamelKey filter? As used in id="{{::form.key|sfCamelKey}}". This is similar to fieldId(), except it's missing the form name part. But I think this could be added?

@Anthropic
Copy link
Member

Yes, the idea is if it is filter based then it can be made up to the user if they want to include form name.
(not that I implemented it that way yet)

@Anthropic Anthropic added this to the 0.9.0 milestone Apr 11, 2016
@Anthropic Anthropic self-assigned this Apr 11, 2016
@Anthropic
Copy link
Member

@AndyStricker have you tried using this PR?
I guess it comes down to whether this capability is better in the core or only in the decorators. I'm leaning on the side of core, in which case I would love to see some test cases added, this will help when the functionality is migrated to the new json-schema-form-core repo too as it will ensure it isn't broken then.

@AndyStricker
Copy link

Update: I implemented a filter in bootstrap-decorator.js based on sfCamelKey that accepts an optional prefix argument to feed something like formCtrl.$name. I have not tested it yet. (I took this as opportunity to switch our code from the old boostrap-decorator to the new builder, but did not finish this yet). Should I add a protractor test?

@Anthropic
Copy link
Member

Words cannot express how much we love tests ;)
There are tests I think they're using karma/chia, I'm on windows so I haven't had time to get them working for me yet...

@AndyStricker
Copy link

Well the asf-bootstrap itself doesn't contain any karma/chia tests yet, only a protractor setup. I managed to run those tests without my changes, but two tests are failing. Still figuring out if it's my environment or not. A karma/chia test may be better suited to test a filter or controller method.

Well I'm currently stuck. I've added a sfCamelKey filter to the bootstrap-decorator.js. This filter was enhanced to support an optional prefix and an optional postfix:

.filter('sfCamelKey', function sfCamelKeyFilter() {
  return function(formKey, prefix, postfix) {
    if (!formKey) { return ''; };
    var key = formKey.slice();
    if (prefix) { key.unshift('' + prefix); }
    if (postfix) { key.push('' + postfix); }
    for (var i = 0; i < key.length; i++) {
      var part = key[i].toLowerCase().split('');
      if (i && part.length) { part[0] = part[0].toUpperCase(); };
      key[i] = part.join('');
    };
    return key.join('');
  };
});

So far so good, but we need a prefix, one that is distinguishable for form instances. I tried to access the form controller exposed at the scope: $scope.formCtrl.$name like this:

<label for="{{form.key | sfCamelKey:formCtrl.$name}}" ...>
<input id="{{form.key | sfCamelKey:formCtrl.$name}}" ...>

But it looks like formCtrl is not always available (the directive configured it as require: ?form, so it may be null). I've no idea how to get the form name attribute value here.

Another possibility is to use the $scope.$id identifier. This will work as long as the identifier is not needed outside the asf form element:

<label for="{{form.key | sfCamelKey:'input':$id}}" ...>
<input id="{{form.key | sfCamelKey:'input':$id}}" ...>

The ugly part is: If the input is placed in a new scope (like ng-if does) we have to write $parent.$id here to have the same value for $id on the label and the input element.

I'm not sure if the filter approach is sufficient here or if we better use the fieldId() method approach.

@Anthropic
Copy link
Member

@AndyStricker ah yes decorator tests differently.
Available scopes is an issue that ASF needs to address, there are a few problems at the moment in my opinion with what is available to the developer and what isn't, I've had the issue myself of not being able to access the root scope without $parent.$parent.$parent.$parent etc...

I was actually thinking of the fieldId() option being called within a filter, but same problem may exist. I wont have any time to think about it more until the weekend though.

@Anthropic
Copy link
Member

@AndyStricker @plong0 this is obviously long overdue, I've started updating the bootstrap decorator in the webpack branch, I agree that fieldId solution may indeed be the better approach, the only request I would have if either of you could help me further, is if we can get the fieldId function logic in the service file re-used for the decorator somehow to make sure changes only ever have to be done once, then I am happy to add it and start migrating the bootstrap webpack branch over to use it.

@AndyStricker
Copy link

@Anthropic Great to hear this. I'll look into this around next week.

@Anthropic
Copy link
Member

Anthropic commented Oct 16, 2016

scope.form.key doesn't return numbers in the new builder so I have had to make a controller and decorator to comprehend what the current actual key is.

I nearly have this working, just need to test it some more during the week.

@Anthropic
Copy link
Member

This should be working in the current develop branch, please let me know if anyone has suggestions on how it could/should be changed or altered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants