我正在使用google places autocomplete控件,它会使用类pac-container
为下拉菜单创建一个元素。
我正在使用ember应用程序中的自动完成功能,当我完成它时,DOM元素自动完成将被删除,但pac-container
元素仍然存在,甚至认为它是隐藏的。下次我实例化一个新的自动完成时,会创建一个新的pac-container
并保留旧的{{1}}。我似乎无法在API上找到类似于dispose方法的内容,那么有没有正确的方法呢?如果不是,我想我应该使用jquery来清理元素。
答案 0 :(得分:6)
我遇到了同样的问题,希望Google最终提供正式的清理方法,但是现在我能够通过手动删除pac-container对象来解决问题,可以在自动完成中找到对象的引用返回的类:
var autocomplete = new google.maps.places.Autocomplete(element, options);
可以在以下位置找到对pac容器元素的引用:
autocomplete.gm_accessors_.place.Mc.gm_accessors_.input.Mc.L
我只是从我的widget析构函数中的DOM中删除了它:
$(autocomplete.gm_accessors_.place.Mc.gm_accessors_.input.Mc.L).remove();
希望这有帮助。
<强>更新强>
我不确定Google的混淆是如何工作的,但上面的部分内容似乎是混淆的,如果API的混淆或内部结构发生变化,显然会失败。对后者无能为力,但对于前者,您至少可以按预期标准搜索对象属性。正如我们所看到的,一些属性名称没有被混淆,而一些属性名称似乎是,例如“Mc”和“L”。为了使其更加健壮,我编写了以下代码:
var obj = autocomplete.gm_accessors_.place;
$.each(Object.keys(obj), function(i, key) {
if(typeof(obj[key]) == "object" && obj[key].hasOwnProperty("gm_accessors_")) {
obj = obj[key].gm_accessors_.input[key];
return false;
}
});
$.each(Object.keys(obj), function(i, key) {
if($(obj[key]).hasClass("pac-container")) {
obj = obj[key];
return false;
}
});
$(obj).remove();
代码期望一般结构保持不变,而不依赖于(可能)混淆的名称“Mc”和“L”。丑陋我知道,但希望谷歌很快解决这个问题。
答案 1 :(得分:2)
我没有jquery的code from above的实现。
var autocomplete = new google.maps.places.Autocomplete(element, options);
export function getAutocompletePacContainer(autocomplete) {
const place: Object = autocomplete.gm_accessors_.place;
const placeKey = Object.keys(place).find((value) => (
(typeof(place[value]) === 'object') && (place[value].hasOwnProperty('gm_accessors_'))
));
const input = place[placeKey].gm_accessors_.input[placeKey];
const inputKey = Object.keys(input).find((value) => (
(input[value].classList && input[value].classList.contains('pac-container'))
));
return input[inputKey];
}
getAutocompletePacContainer(autocomplete).remove()
答案 2 :(得分:1)
现在适用于Google更改班级名称。
autocomplete.addListener('place_changed', function() {
$('.pac-container').remove();
});
答案 3 :(得分:0)
内置此递归函数以在自动完成对象中定位元素位置。
var elementLocator = function(prop, className, maxSearchLevel, level) {
level++;
if (level === (maxSearchLevel + 1) || !prop || !(Array.isArray(prop) || prop === Object(prop))) {
return;
}
if (prop === Object(prop) && prop.classList && prop.classList.contains && typeof prop.classList.contains === 'function' && prop.classList.contains(className)) {
return prop;
}
for (const key in prop) {
if (prop.hasOwnProperty(key)) {
var element = elementLocator(prop[key], className, maxSearchLevel, level);
if (element) {
return element;
}
}
}
};
用法:
var elm = null;
try {
//set to search first 12 levels, pass -1 to search all levels
elm = elementLocator(this.autocomplete, 'pac-container', 12, null);
} catch(e) {
console.log(e);
}
答案 4 :(得分:0)
我也刚刚遇到了这个问题。这可能与我的输入字段位于flexbox内有关,但我还没有尝试重组我的页面。相反,我在输入字段中添加了onfocus侦听器,并在其容器中添加了onscroll侦听器。在内部,我用getBoundingClientRect
获得输入字段的位置,然后用这些值更新样式表。我尝试通过.pac-container
直接选择和更新document.querySelctor
,但这似乎不起作用。您可能需要setTimeout才能将其首先添加到DOM。
这是我的代码:
let ruleIndex = null;
const form = document.body.querySelector('.form');
const input = document.body.querySelector('.form-input');
const positionAutoComplete = () => {
const { top, left, height } = inputField.getBoundingClientRect();
if(ruleIndex) document.styleSheets[0].deleteRule(ruleIndex);
ruleIndex = document.styleSheets[0].insertRule(`.pac-container { top: ${top + height}px !important; left: ${left}px !important; }`);
}
form.addEventListener('scroll', positionAutoComplete);
input.addEventListener('focus', positionAutoComplete);
如先前的回答中所述,这中断了Google决定重命名.pac-container
的时间,因此不是完美的解决方案,但可同时进行。