How to define a mask for the phone number according to the format presented by the placeholder attribute of the ngx-intl-tel-input component?
I found a solution for me. My ngx-intl-tel-input component is an angular formControl. So, I used the valueChanges event of this formControl to aply a mask:
ngOnInit() {
this.confirmForm = this.formBuilder.group({
cellPhone: [{ number: this.currentUser.number, countryCode: this.currentUser.countryCode }, [Validators.required]],
code: ['', [Validators.required, Validators.minLength(6)]],
id: [this.currentUser.id]
});
this.confirmForm.get("cellPhone").valueChanges.subscribe(x => {
//aply the mask
})}
hope it helps
this.confirmForm.get("cellPhone")!.valueChanges.pipe(
throttleTime(200),
tap((x)=>{
if(x?.number){
let nums = x.number.replace(/\D/g, '').match(/(\d{0,3})(\d{0,2})(\d{0,2})(\d{0,2})/);
if(nums) {
let masked = !nums[2] ? nums[1] : '' + nums[1] + ' ' + nums[2] + (nums[3] ? ' ' + nums[3] : '') + (nums[4] ? ' ' + nums[4] : '');
this.confirmForm.get("cellPhone")!.setValue(masked);
}
}
})).subscribe((x: any) => { });
Related
I'm using vuejs and vuex for creating my project and I want to optionally choose filter out of this url filters. For ex: when i want to choose only city and car filter, there will be only city and car url's (...?city_id=2&car__car_model=11), but now, when I'm send id's to this action, I should send id's I want and others as blank ('') and then output is ...?city_id=2&sub_category=&sub_category=&car__car_model=&limit=&offset=.
That's my javascript code:
async filteredServices ({ commit, dispatch }, cityId = '', subCat = '', car = '', limit = '', offset = '') {
const url = 'test/service/' + '?city_id=' + cityId + '&sub_category=' + subCat + '&car__car_model=' + car + '&limit=' + limit + '&offset=' + offset
console.log('url', url)
const response = await dispatch('api/test/get', { url }, { root: true })
if (response.status === 200) {
commit('setCompanyService', response.data.results)
console.log('setCompanyService', response.data.results)
}
},
That's my html script code:
applyFilter () {
this.filteredServices(this.selectedCityId)
}
And I also try to use like this:
async filteredServices ({ commit, dispatch }, form) {
const url = 'test/service/' + '?city_id=' + form.cityId + '&sub_category=' + form.subCat + '&car__car_model=' + form.car + '&limit=' + form.limit + '&offset=' + form.offset
const response = await dispatch('api/test/get', { url }, { root: true })
if (response.status === 200) {
commit('setCompanyService', response.data.results)
console.log('setCompanyService', response.data.results)
}
},
and html code script:
applyFilter () {
this.filteredServices({
cityId: this.selectedCityId,
car: '',
subCat: 3360,
limit: '',
offset: ''
})
}
And the main question is, How to clear write url filtering with optionally choosing the filter what I want in vuejs vuex actions.
Im trying to render a form dynamically using "for" loop, and its renders good but when I tried to change the value in a picker, it changed but it immediately changes to the default value, so what i need to do to fix this?
class Datos extends Component {
cotizadorData: any;
planesData: any;
dataStructure =
{
id: 1,
name: '',
lastName: '',
email: '',
documentNumber: '',
dateOfBirth: '',
age: '',
gender: 'M',
areaCode: '',
phoneNumber: '',
medicalObservation: 'Sin Observaciones'
};
emergencyContactDataStructure =
{
name: '',
email: '',
areaCode: '',
phoneNumber: ''
};
planCode: string = '';
departurePlaceCode: string = '';
arrivalPlaceCode: string = '';
passengersArray: Array = [];
additionalPassengersCount: number = 0;
additionalPassengersArray: Array = [];
additionalPassengersView: Array = [];
__isMounted: string = 'false';
mainPassengerAreaCodeRef: any;
emergencyContactAreaCodeRef: any;
apiKey: string = '';
xmlForOrder: string = '';
constructor(){
super();
this.state = {
showLoader: false,
countries : [ {
label: '',
value: ''
} ],
holderData: this.dataStructure,
additionalPassengers: [],
additionalPassengersView: [],
emergencyContact: this.emergencyContactDataStructure
};
}
async componentDidMount () : void {
this.setState({
showLoader: true
});
await AsyncStorage.setItem('dataComponentIsMounted', 'true');
this.apiKey = await AsyncStorage.getItem('apiKey');
this.xmlForCountries = getCountries(this.apiKey);
this.countries = await getOrbisDataServer(this.xmlForCountries);
this.processCotizadorData();
this.setState({
departurePlace: this.countries[0].description
});
this.formatArraysForPickers();
};
updateAsyncStorage = async() => {
this.__isMounted = await AsyncStorage.getItem('dataComponentIsMounted');
if(!isUndefinedOrNull(this.__isMounted))
{
if(this.__isMounted === 'true')
{
this.processCotizadorData();
}
}
};
processCotizadorData = async() => {
this.additionalPassengersCount = 0;
this.additionalPassengersArray = [];
this.cotizadorData = await AsyncStorage.getItem('cotizadorData');
this.planesData = JSON.parse(await AsyncStorage.getItem('planesData'));
if(!isUndefinedOrNull(this.cotizadorData))
{
this.cotizadorData = JSON.parse(this.cotizadorData);
this.additionalPassengersCount = (this.cotizadorData.youngs + this.cotizadorData.adults +
this.cotizadorData.semiSeniors + this.cotizadorData.seniors) - 1;
let id = 2;
for(let i = 0; i < this.additionalPassengersCount; i++)
{
this.additionalPassengersArray.push({
id: id,
name: '',
lastName: '',
email: '',
documentNumber: '',
dateOfBirth: '',
age: '',
gender: 'M',
areaCode: '',
phoneNumber: '',
medicalObservation: 'Sin Observaciones'
});
id++;
}
this.setState({
additionalPassengers: this.additionalPassengersArray
});
this.renderAdditionalPassengersForms();
}
};
setAdditionalPassengerGender = (additionalPassenger, value) => {
let additionalPassengersModified = [...this.state.additionalPassengers];
let index = additionalPassengersModified.findIndex(el => el.id === additionalPassenger.id);
additionalPassengersModified[index] = {...additionalPassengersModified[index], gender: value};
this.setState({
additionalPassengers: additionalPassengersModified
});
};
renderAdditionalPassengersForms = () => {
for(let i = 0; i < this.additionalPassengersArray.length; i++)
{
this.additionalPassengersView.push(
<View>
<Text style={[styles.normalFont, styles.label]}>SEX</Text>
<Picker
selectedValue={this.state.additionalPassengers[i].gender}
style={{height: 50, width: 100}}
onValueChange={(value) => {this.setAdditionalPassengerGender (this.additionalPassengersArray[i], value)}}>
<Picker.Item label="Male" value="M"/>
<Picker.Item label="Female" value="F"/>
</Picker>
</View>
)
}this.setState({
additionalPassengersView: this.additionalPassengersView
});
}
I expect to change the picker value for selected one.
Edited: I added the whole component
Since your UI has no issue pilling up views on this.additionalPassengersView, I suppose renderAdditionalPassengersForms is not called everytime the value in any of the additional passengers pickers change.
You problem is: selectedValue on Picker has to be updated when you make a choice. Otherwise, the picker will roll back to its non-updated selected value, as the behavior you describe.
I use redux-form to manage my forms. But, assuming you don't want to use it, you can make a new component for the picker, putting the picker selected value on the state and updating this state on onValueChange callback
I'm using FormData() in my React app. I was going to use it for registration and login too. I have a working passport.js registration piece of code and was going to use it with busboy but it looks like it reads fields one by one whenever there is one and it seems like I can't use it with Account.register.
I've inserted Account.register in busboy.on('field') but then realized it won't work. I didn't change req.body.username etc in my original code, ignore them.
busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) {
console.log('Field [' + fieldname + ']: value: ' + inspect(val));
Account.register(new Account({ nickname: req.body.username, email: req.body.email }), req.body.passwordOne, (err, user) => {
if(err){
helpers.errors(err, res);
} else {
helpers.registerSuccess(res);
}
});
});
busboy.on('finish', function() {
console.log('Done parsing form!');
//res.writeHead(303, { Connection: 'close', Location: '/' });
res.end();
});
I'm using nickname instead of username in passport.js because I'm using email as the username field. Working code:
router.post('/register', (req, res, next)=>{
var busboy = new Busboy({ headers: req.headers });
let nickname = '';
let email = '';
let password = '';
busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
console.log('File [' + fieldname + ']: filename: ' + filename + ', encoding: ' + encoding + ', mimetype: ' + mimetype);
file.on('data', function(data) {
console.log('File [' + fieldname + '] got ' + data.length + ' bytes');
});
file.on('end', function() {
console.log('File [' + fieldname + '] Finished');
});
});
busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) {
console.log('Field [' + fieldname + ']: value: ' + inspect(val));
if(fieldname == 'username') { nickname = val; }
if(fieldname == 'email') { email = val; }
if(fieldname == 'password') { password = val; }
});
busboy.on('finish', function() {
console.log('Done parsing form!');
console.log('email: ' + email + 'password: ' + password + 'username: ' + nickname);
Account.register(new Account({ nickname: nickname, email: email }), password, (err, user) => {
if(err){
helpers.errors(err, res);
} else {
helpers.registerSuccess(res);
}
});
});
req.pipe(busboy);
});
I have placed a textbox widget inside grid cell by using formatter. However, I cannot move my cursor around nor select text inside the textbox.
E.g.
http://jsfiddle.net/g33m9/69/
Does anyone know how to fix this?
Thanks
You need to set the column as 'editable' so that the Grid component will know how to handle keypressed events. So a modification to the layout is in order
from
var layout = [[
{name: 'Column 1', field: 'col1'},
{name: 'Column 2', field: 'col2', width:'200px', formatter: func}
]];
to
var layout = [[
{name: 'Column 1', field: 'col1'},
{name: 'Column 2', field: 'col2', width:'200px', formatter: func, editable: true}
]];
Edit state activates by doubleclick.
Now, OP wants it to be a fully bloated widget, popping up in the editable state. For this to be scaleable up with any number of rows/columns i will restrict this to the edit state, so that the value simply shows text but once double-clicked it will pop a FilteringSelect. Same principle goes with the dijit widget ValidationTextBox.
Currently (1.7.2) the possible celltypes are:
dojox.grid.cells.Bool
dojox.grid.cells.ComboBox
dojox.grid.cells.DateTextBox
dojox.grid.cells.Select
Catch me SEO:
example of custom dojox.grid cellType widget - semi-programmatic
First step - create some data
var i = 0,
data = {
identifier: 'id',
items: [
{ id: i, value: 'val'+i++},
{ id: i, value: 'val'+i++},
{ id: i, value: 'val'+i++},
{ id: i, value: 'val'+i++}
]
},
// The item label which holds visible value and which holds the value to represent
searchAttr = 'value',
valueAttr = data.identifier,
// The store to use for select widget
store = new dojo.data.ItemFileReadStore({ data: data }),
// And the options, reassembling the valid options we will present in dropdown
// Used when cellType is dojox.grid.cells.Select to name the allowable options
options = [];
dojo.forEach(data.items, function(it) { options.push(it[searchAttr])});
Tricky part - Define a cellType
Lets extend the existing dojox.grid.cells.Cell, it has two key features - an edit-state-formatter and the default-formatter. The default would work just fine. Last but not least, we'll override the '_finish' function allthough allow the Cell to process its own definition too.
var whenIdle = function( /*inContext, inMethod, args ...*/ ) {
setTimeout(dojo.hitch.apply(dojo, arguments), 0);
};
var FilteringSelectCell = declare("dojox.grid.cells.FilteringSelect", [dojox.grid.cells.Cell], {
options: null,
values: null,
_destroyOnRemove: true,
constructor: function(inCell){
this.values = this.values || this.options;
},
selectMarkupFactory: function(cellData, rowIndex) {
var h = ['<select data-dojo-type="dijit.form.FilteringSelect" id="deleteme' + rowIndex + '" name="foo">'];
for (var i = 0, o, v;
((o = this.options[i]) !== undefined) && ((v = this.values[i]) !== undefined); i++) {
v = v.replace ? v.replace(/&/g, '&').replace(/</g, '<') : v;
o = o.replace ? o.replace(/&/g, '&').replace(/</g, '<') : o;
h.push("<option", (cellData == v ? ' selected' : ''), ' value="' + v + '"', ">", o, "</option>");
}
h.push('</select>');
return h;
},
textMarkupFactory: function(cellData, rowIndex) {
return ['<input class="dojoxGridInput" id="deleteme' + rowIndex + '" data-dojo-type="dijit.form.ValidationTextBox" type="text" value="' + cellData + '">']
},
// #override
formatEditing: function(cellData, rowIndex) {
this.needFormatNode(cellData, rowIndex);
var h = (cellData == "W1")
? this.textMarkupFactory(cellData, rowIndex)
: this.selectMarkupFactory(cellData, rowIndex);
// a slight hack here, i had no time to figure out when the html would actually be inserted to the '<td>' so.. Use 'debugger' statement and track function to hook into
whenIdle(function() {
dojo.parser.parse(dojo.byId('deleteme' + rowIndex).parentNode);
var w = dijit.byId('deleteme' + rowIndex);
w.focus()
});
return h.join('');
},
// clean up avoiding multiple widget definitions 'hanging'
_finish: function(inRowIndex) {
this.inherited(arguments)
dijit.byId('deleteme' + inRowIndex).destroy();
},
// needed to read the value properly, will work with either variant
getValue: function(rowIndex) {
var n = this.getEditNode(rowIndex);
n = dijit.getEnclosingWidget(n);
return n.get("value");
}
});
Last bit, a new layout
var layout = [[
{ name: 'Column 1', field: 'col1' },
{ name: 'Column 2', field: 'col2',
cellType: FilteringSelectCell, options: options, editable: true
}
]];
Running sample here http://jsfiddle.net/dgbxw/1/
I'm trying to add this short function - which swaps images according to the active tab in jQuery UI Tabs - below to the larger function below, which is the jQuery Address plugin that adds forward/back and #URL functions to UI Tabs: http://www.asual.com/jquery/address/
I need to add the shorter function so it fires when the tab changes - so it changes the image in #headerwrapper - but I can't quite tell exactly where the tab change is fired in the main address function. Any ideas on how to add this shorter function to jQuery Address?
Image change function I need to add to the main function below to run when the tab change fires:
var img = $(ui.panel).data("image");
$("#headerwrapper")
.animate({ opacity: 'toggle' }, function() {
$(this).css("background-image", "url(" + img + ")")
.animate({ opacity: 'toggle' });
});
}
Main jQuery Tabs Address function:
<script type="text/javascript">
var tabs,
tabulation = false,
initialTab = 'home',
navSelector = '#tabs .ui-tabs-nav',
navFilter = function(el) {
return $(el).attr('href').replace(/^#/, '');
},
panelSelector = '#tabs .ui-tabs-panel',
panelFilter = function() {
$(panelSelector + ' a').filter(function() {
return $(navSelector + ' a[title=' + $(this).attr('title') + ']').size() != 0;
}).each(function(event) {
$(this).attr('href', '#' + $(this).attr('title').replace(/ /g, '_'));
});
};
if ($.address.value() == '') {
$.address.value(initialTab);
}
$.address.init(function(event) {
$(panelSelector).attr('id', initialTab);
$(panelSelector + ' a').address(function() {
return navFilter(this);
});
panelFilter();
tabs = $('#tabs')
.tabs({
load: function(event, ui) {
$(ui.panel).html($(panelSelector, ui.panel).html());
panelFilter();
},
fx: {
opacity: 'toggle',
duration: 'fast'}
})
.css('display', 'block');
$(navSelector + ' a').click(function(event) {
tabulation = true;
$.address.value(navFilter(event.target));
tabulation = false;
return false;
});
}).change(function(event) {
var current = $('a[href=#' + event.value + ']:first');
$.address.title($.address.title().split(' - ')[0] + ' - ' + current.text());
if (!tabulation) {
tabs.tabs('select', current.attr('href'));
}
}).history(true);
document.write('<style type="text/css"> #tabs { display: none; } </style>');
</script>